]> cloudbase.mooo.com Git - kermit-80.git/blob - cpxsb.asm
Add AVR-CP/M system (cpxac.asm) and a Makefile
[kermit-80.git] / cpxsb.asm
1 IF NOT lasm
2 .printx * CPXSB.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 ; This file created 16 July, 1987 by OBSchou from code submitted
22 ; by William Rose for the Micromint SB180 systems (as featured in
23 ; BYTE magazine, 1986). This file has been modified to fit in with
24 ; Kermit-80 V4.08 etc. His file KERSYS.ASM is a stripped down version
25 ; of CPXSYS.ASM (formerly CP4SYS.ASM).
26 ;
27 ; revision history:
28 ; KERSYS.ASM - version 0.8 dated 13 Jul 87.
29 ;
30 ; Cutdown CP4SYS.ASM for SB-180/Ampro 230.
31 ;
32 ;
33 ; While this is a single CPU version (to ease editing) the assembler
34 ; conditionals have been kept to identify machine specific code.
35 ;
36 ; Note that the baud setting routine also sets parity, but this does not
37 ; change the parity given by Kermit's 'stat' command. I assume that the
38 ; main body of the program does its own parity check.
39 ;
40 ; Revision history (last entry first)
41 ;
42 ; edit 2, 22 July by OBSchou to massage file to fit with CPXCOM.ASM.
43 ;
44 ; edit 1, 15 July, 1987 by OBSchou for William Rose who submitted
45 ; the code for Kermit-80 V 4.05. Modified code as appropriate
46 ; for 4.08 compatability.
47 ;
48
49 delfac EQU 150 ; Delay factor in SB-180 input loop - a fudge
50
51 ;
52 ; Keep module name, edit number, and last revision date in memory.
53 ;
54 ;sysedt: db 'KERSYS.ASM (03) 12-FEB-87 $' ; last SB-180 revision
55 ;sysedt: db 'KERSYS.ASM (04) 12-APR-87 $' ; Telecom Merlin added
56 ;sysedt: db 'KERSYS.ASM (5) 9-May-87 $' ; Minor tidying
57 ;sysedt: db 'KERSYS.ASM (6A) 17-Jun-87 $' ; BT Merlin M2215 only
58 ;sysedt: db 'KERSYS.ASM (7) 19-Jun-87 $' ; SB-180 only
59 ;sysedt: db 'KERSYS.ASM (8) 13-Jul-87 $' ; 6/9 MHz version
60 family: db 'CPXSB.ASM (2) 22-Jul-87$' ; First entry for V4.08/9
61
62 ;
63 ; Assembly time message to let me know I'm building the right version.
64 ;
65
66 IF sb180
67 .printx * Assembling Kermit-80 for Micromint SB-180 *
68 ENDIF
69
70
71 IF sb180
72 mnctrla EQU 000H ;Modem control port - CNTLA0
73 mnctrlb EQU 002H ;Modem control port - CNTLB0
74 mnstat EQU 004H ;Modem status port - STAT0
75 mntxdat EQU 006H ;Modem output port - TDR0
76 mnrddat EQU 008H ;Modem input port - RDR0
77 output EQU 002H ;Transmit data register empty mask - TDRE
78 input EQU 080H ;Receive data register full mask - RDRF
79 z80 EQU TRUE ;This one's an HD64180, but Z80 will do
80 ENDIF
81
82
83 sysxin: ; continuation of system initialisation from sysinit
84
85 IF sb180
86 lxi h, porbuf ; park the original settings
87 db 0EDh, 038h, mnctrla ; HD64180 code IN0 g,(m)
88 mov m, a
89 inx h
90 db 0EDh, 038h, mnctrlb
91 mov m, a
92 inx h
93 db 0EDh, 038h, mnstat
94 mov m, a
95 ENDIF
96 ; re-initialise for KERMIT
97 IF sb6
98 mvi h, 08h ; 0000$1001 - 9600 baud, (even) parity
99 mvi l, 08h ; 'speed' is two bytes
100 ENDIF
101
102 IF sb9
103 mvi h, 21h ; 0010$0001 - 9600 baud, (even) parity
104 mvi l, 21h ; 'speed' is two bytes
105 ENDIF
106
107 IF sb180
108 shld speed
109 lxi h, parind
110 mvi m, 8 ; index for 8 bits, no parity, 2 stop
111 call setpor
112 ENDIF
113
114 ret
115
116 porbuf: ds 3 ; original port settings
117
118 ;
119 ; system-dependent KERMIT termination processing
120 ; If we've changed anything, this is our last chance to put it back.
121 ;
122 sysexit:
123
124 IF sb180
125 lxi h, porbuf
126 mov a, m ; output parity
127 db 0EDh, 039h, mnctrla ; HD64180 code OUT0 (m),g
128 inx h
129 mov a, m ; output baud rate
130 db 0EDh, 039h, mnctrlb
131 inx h
132 mov a, m ; output to clear error flags
133 db 0EDh, 039h, mnstat
134 ; read twice to reset DCD0 ?
135 db 0EDh, 038h, mnstat
136 db 0EDh, 038h, mnstat
137 ENDIF
138
139 ret
140
141 ;
142 ; system-dependent processing for start of CONNECT command
143 ;
144 syscon:
145 ret
146
147 conmsg: ; Messages printed when entering transparent (CONNECT) mode:
148
149 db '$'
150
151 ;
152 ; syscls - system-dependent close routine
153 ; called when exiting transparent session.
154 ;
155 syscls:
156 ret
157
158 ;
159 ; sysinh - help for system-dependent special functions.
160 ; called in response to <escape>?, after listing all the
161 ; system-independent escape sequences.
162 ;
163 sysinh:
164
165 IF sb180
166 lxi d, inhlps
167 call prtstr
168 ENDIF
169
170 ret
171
172 ; Additional, system-dependent help for transparent mode
173 ; (two-character escape sequences)
174 inhlps:
175
176 IF sb180
177 db cr, lf, 'V Cycle port parameters'
178 ENDIF
179
180 db '$' ; string terminator
181
182 ;
183 ; sysint - system dependent special functions
184 ; called when transparent escape character has been typed;
185 ; the second character of the sequence is in A (and in B).
186 ; returns:
187 ; non-skip: sequence has been processed
188 ; skip: seqence was not recognized
189 ;
190 sysint:
191 ; ani 137O ; convert lower case to upper, for testing...
192 ; does this work?
193 IF sb180
194 cpi 'V' ; cycle port ?
195 jz pcycl
196 cpi 'v'
197 jz pcycl
198 ENDIF
199
200 jmp rskp ; take skip return - command not recognised
201
202 ; Actual commands
203
204 IF sb180
205 pcycl:
206 lxi h, parind ; increment parval, modulo 12
207 mov a, m
208 adi 1
209 cpi 13
210 jnz pcy1
211 mvi a, 1
212 pcy1: mov m, a ; update the storage
213 ; get index of name in parstr
214 ora a ; clear flags
215 dcr a
216 rlc
217 rlc
218 mov c, a
219 mvi b, 0
220 lxi h, parstr
221 inx h
222 dad b
223 push h
224 lxi d, cgmsg1
225 call prtstr
226 pop d
227 call prtstr
228 lxi d, cgmsg2
229 call prtstr
230 call setpor ; reset the port
231
232 ret
233
234 cgmsg1: db '<$'
235 cgmsg2: db '>$'
236 ENDIF
237
238 ret
239
240 ;
241 ; Delay routine. Called with time (hundredths of seconds) in A.
242 ; The inner loop delays 1001 T-states, assuming no wait states are
243 ; inserted; this is repeated CPUSPD times, for a total delay of just
244 ; over 0.01 second. (CPUSPD should be set to the system clock rate,
245 ; in units of 100KHz: for an unmodified Kaypro II, that's 25 for
246 ; 2.5 MHz. Some enterprising soul could determine whether or not the
247 ; Kaypro actually inserts a wait state on instruction fetch (a common
248 ; practice); if so, the magic number at delay2 needs to be decreased.
249 ; (We also neglect to consider time spent at interrupt level).
250 ;
251 ; called by: sendbr
252 ; destroys BC
253 ;
254 ;delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to
255 ; ; make .01 second delay
256 ;delay2: mvi b,70 ; Number of times to execute inner loop to
257 ; ; make 1000 T-state delay
258 ;delay3: dcr b ; 4 T-states (* 70 * cpuspd)
259 ; jnz delay3 ; 10 T-states (* 70 * cpuspd)
260 ; dcr c ; 4 T-states (* cpuspd)
261 ; jnz delay2 ; 10 T-states (* cpuspd)
262 ; ; total delay: ((14 * 70) + 14) * cpuspd
263 ; ; = 1001 * cpuspd
264 ; dcr a ; 4 T-states
265 ; jnz delay ; 10 T-states
266 ;
267 ; ret ; grand total: ((1001 * cpuspd) + 14) * a
268
269 ;
270 ; sysflt - system-dependent filter
271 ; called with character in E.
272 ; if this character should not be printed, return with A = zero.
273 ; preserves bc, de, hl.
274 ; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
275 ;
276 sysflt:
277 mov a,e ; get character for testing
278 ret
279
280 ;
281 ; mdmflt - modem filter
282 ; called with character to be sent to printer in E
283 ; with parity set as appropriate.
284 ; return with accumulator = 0 do do nothing,
285 ; <> 0 to send char in E.
286 mdmflt:
287 mov a,e ; get character to test
288 ret
289
290 ;
291 ; prtflt - printer filter
292 ; called with character to be sent to printer in E
293 ; returns with a = 0 to do nothing
294 ; a <> 0 to print it.
295 ;
296 ; this routine for those printer that automatically insert
297 ; a lf on cr, or cr for lf. Should this be shifted to
298 ; the system indep. stuff, in say 4.06?
299 ;
300 prtflt:
301 mov a,e ; get character to test
302
303 IF FALSE ; strip out lf from printer stream
304 ani 7fh ; make sure it is parity less
305 cpi lf ; is it a line feed?
306 rnz ; no, print it
307 ; xra a ; yes, don't.
308
309 ENDIF
310
311 ret
312
313 ;
314 ; system-dependent processing for BYE command.
315 ;
316 sysbye:
317 ret
318
319 ;
320 ; This is the system-dependent command to change the baud rate.
321 ; DE contains the two-byte value from the baud rate table; both
322 ; bytes of this value are also stored in 'speed'.
323 ;
324 sysspd:
325
326 IF sb180
327 lxi d, prtmsg ; ask for variables
328 call prtstr
329
330 lxi d, tbuf ; get suitable string
331 mvi c, 10
332 call bdos
333
334 lxi h, tbuf1
335 mov a, m
336 ora a
337 jz setpor ; leave unchanged if string zero length
338
339 cpi 3 ; check given length
340 jnz spd1 ; error - wrong length
341 inx h
342 inx h
343 mov a, m
344 ani 137O ; convert parity code to upper case
345 mov m, a
346
347 lxi d, tbuf1 ; get index of given parameter
348 lxi h, parstr
349 call sposn
350 ora a
351 jnz spd2 ; or fall through if error
352 spd1: lxi d, invmsg ; invalid input - try again
353 call prtstr
354 jmp sysspd
355
356 spd2: adi 3 ; get index to parval table
357 rrc ; by dividing by 4
358 rrc
359 ani 15 ; mask out high bits
360 lxi h, parind
361 mov m, a ; and store it
362 call setpor ; set up port iaw index and speed bytes
363
364 ret
365
366 prtmsg: db cr,lf,'Enter bit/char, parity, and stop bits required.'
367 db cr,lf,'(Bit 7/8 Parity N/O/E Stop 1/2 - CR same) : $'
368 invmsg: db cr,lf,'Invalid parameters$'
369
370 parind: db 8 ; default <8N2> index
371 parstr: db 48,'7N1$7N2$7O1$7O2$7E1$7E2$'
372 db '8N1$8N2$8O1$8O2$8E1$8E2$'
373 parval: db 0,1,16+2,16+3,2,3
374 db 4,5,16+6,16+7,6,7
375 tbuf db 6
376 tbuf1 db 3,'8N2','$$$$'
377
378 ;
379 ; Set up the port using the table index in parind and the speed byte
380 ;
381 setpor:
382 lxi h, parind
383 mov a, m
384 dcr a
385 lxi h, parval ; table base
386 mvi b, 0
387 mov c, a
388 dad b ; HL points at parameter value
389 mov a, m
390 mov b, a ; park parval
391
392 ani 16 ; the parity switch bit
393 lxi h, speed
394 add m ; this is now the baud rate byte
395 mov c, a ; park it
396
397 mov a, b ; sort out the parameter byte
398 ani 7 ; b/p/s only wanted
399 adi 96 ; RE, TE enable
400 db 0EDh,039h,mnctrla ; output parity etc.
401 mov a, c
402 db 0EDh,039h,mnctrlb ; output baud rate
403 mvi a, 0
404 db 0EDh,039h,mnstat ; clear status
405 db 0EDh,038h,mnstat ; read twice to reset DCD0
406 db 0EDh,038h,mnstat
407 ret
408
409 ;
410 ; Find substring position - Leventhal page 293, modified
411 ; enter with subtring in DE and string in HL
412 ; returns index in A or 0 for failure
413 ;
414 sposn:
415 mov a, m ; exit if either string length zero
416 ora a
417 jz notfnd
418 sta slen
419 mov b, a
420 inx h
421 shld string
422 xchg
423 mov a, m
424 ora a
425 jz notfnd
426 sta sublen
427 mov c, a
428 inx h
429 shld substg
430 mov a, b
431
432 ; no of searches = stringlen - substrlen + 1
433 ; if substr longer than string quit immediately
434
435 sub c
436 jc notfnd
437 inr a
438 mov c, a
439 xra a
440 sta index
441
442 ; search until remaining string shorter than substring
443
444 slp1: lxi h, index
445 inr m
446 lda sublen
447 mov b, a
448 lhld substg
449 xchg
450 lhld string
451
452 ; try to match substring starting at index
453
454 cmplp: ldax d
455 cmp m
456 jnz slp2
457 dcr b
458 jz found
459 inx h
460 inx d
461 jmp cmplp
462
463 ; arrive here if match fails
464
465 slp2: dcr c
466 jz notfnd
467 lhld string
468 inx h
469 shld string
470 jmp slp1
471
472 ; found, return index
473
474 found: lda index
475 ret
476
477 ; not found, return zero
478
479 notfnd: sub a
480 ret
481
482 string: ds 2
483 substg: ds 2
484 slen: ds 1
485 sublen: ds 1
486 index: ds 1
487 ENDIF
488
489 ret
490
491 ;
492 ; Speed tables
493 ; (Note that speed tables MUST be in alphabetical order for later
494 ; lookup procedures, and must begin with a value showing the total
495 ; number of entries. The speed help tables are just for us poor
496 ; humans.
497 ;
498 ; db string length, string, divisor (2 bytes or 1 word, ab)
499 ; the data byte a is return in A and E, and b in D
500 ; only byte 'a' is the key for the table
501
502 IF sb6
503 spdtbl: db 9 ; 9 entries
504 db 04h,'1200$', 0Bh,0Bh
505 db 03h,'150$', 0Eh,0Eh
506 db 05h,'19200$', 01h,01h
507 db 04h,'2400$', 0Ah,0Ah
508 db 03h,'300$', 0Dh,0Dh
509 db 05h,'38400$', 00h,00h
510 db 04h,'4800$', 09h,09h
511 db 03h,'600$', 0Ch,0Ch
512 db 04h,'9600$', 08h,08h
513
514 sphtbl: db cr,lf
515 db ' 150 300 600 1200 2400 4800 9600 19200 38400$'
516 ENDIF
517
518 IF sb9
519 spdtbl: db 7 ; 7 entries
520 db 04h,'1200$', 24h,24h
521 db 05h,'19200$', 20h,20h
522 db 04h,'2400$', 23h,23h
523 db 03h,'300$', 26h,26h
524 db 04h,'4800$', 22h,22h
525 db 03h,'600$', 25h,25h
526 db 04h,'9600$', 21h,21h
527
528 sphtbl: db cr,lf
529 db ' 300 600 1200 2400 4800 9600 19200$'
530 ENDIF
531
532
533 ;
534 ; This is the system-dependent SET PORT command.
535 ; HL contains the argument from the command table.
536 ;
537 sysprt:
538 ret
539
540 IF sb180
541 prttbl EQU 0 ; SET PORT is not supported
542 prhtbl EQU 0
543 ENDIF
544
545 ;
546 ; selmdm - select modem port
547 ; selcon - select console port
548 ; selmdm is called before using inpmdm or outmdm;
549 ; selcon is called before using inpcon or outcon.
550 ; For iobyt systems, diddle the I/O byte to select console or comm port;
551 ; For the rest, does nothing.
552 ; preserves bc, de, hl.
553 ;
554 selmdm:
555 ret
556
557 selcon:
558 ret
559
560 ;
561 ; Get character from console, or return zero.
562 ; result is returned in A. destroys bc, de, hl.
563 ;
564 inpcon:
565 mvi c,dconio ;Direct console I/O BDOS call.
566 mvi e,0FFH ;Input.
567 call BDOS
568
569 ret
570
571 ;
572 ; Output character in E to the console.
573 ; destroys bc, de, hl
574 ;
575 outcon:
576 mvi c,dconio ;Console output bdos call.
577 call bdos ;Output the char to the console.
578
579 ret
580
581 ;
582 ; outmdm - output a char from E to the modem.
583 ; the parity bit has been set as necessary.
584 ; returns nonskip; bc, de, hl preserved.
585 ;
586 outmdm:
587
588 IF sb180
589 db 0EDh,038h,mnstat
590 ani output ; check status
591 jz outmdm ; wait until port is available
592 mov a, e
593 db 0EDh,039h,mntxdat ; transmit
594 ENDIF
595
596 ret
597
598 ;
599 ; get character from modem; return zero if none available.
600 ; for IOBYT systems, the modem port has already been selected.
601 ; destroys bc, de, hl.
602 ;
603 inpmdm:
604
605 IF sb180
606 lxi h, delfac ; loops to give delay
607 inpm1: db 0EDh,038h,mnstat
608 ani input ; check status
609 jz inpm2
610 db 0EDh,038h,mnrddat ; get a byte
611 ret
612
613 inpm2: dcx h ; no data
614 mov h, a
615 ora l
616 jnz inpm1 ; still tries left
617 ret ; with zero in A
618 ENDIF
619
620 ret
621
622 ;
623 ; flsmdm - flush comm line.
624 ; Modem is selected.
625 ; Currently, just gets characters until none are available.
626 ;
627 flsmdm:
628 call inpmdm ; Try to get a character
629 ora a ; Got one?
630 jnz flsmdm ; If so, try for another
631 ret ; Receiver is drained. Return.
632
633 ;\f
634
635 ;
636 ; lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
637 lptstat:
638 IF iobyte ;[33]
639 call bprtst ; get status
640 ENDIF ;iobyte[33]
641 IF NOT iobyte ;[33]
642 xra a ; assume it is ok.. this may not be necessary
643 ENDIF ;iobyte [33]
644 ret
645 ;
646 ; outlpt - output character in E to printer
647 ; console is selected.
648 ; preserves de.
649 ;
650 outlpt:
651 push d ; save DE in either case
652 call prtflt ; go through printer filter [30]
653 ana a ; if A = 0 do nothing,
654 jz outlp1 ; if a=0 do nothing
655
656 outlp1: pop d ; restore saved register pair
657 ret
658
659 ; delchr - make delete look like a backspace. Unless delete is a printing
660 ; character, we just need to print a backspace. (we'll output clrspc
661 ; afterwards)
662 delchr:
663
664 mvi e,bs ;get a backspace
665 jmp outcon
666
667 ; erase the character at the current cursor position
668 clrspc: mvi e,' '
669 call outcon
670 mvi e,bs ;get a backspace
671 jmp outcon
672
673 ; erase the current line
674 clrlin: lxi d,eralin
675 jmp prtstr
676
677 ; erase the whole screen, and go home. preserves b (but not c)
678 clrtop: lxi d,erascr
679 jmp prtstr
680
681 IF sb180
682 sysver: db 'MicroMint SB 180 '
683 ENDIF
684
685 IF sb6
686 db ' (6 MHz)'
687 ENDIF
688
689 IF sb9
690 db ' (9 MHz)'
691 ENDIF
692 db '$'
693
694 IF lasm
695 LINK CPXVDU.ASM ; get terminal defs etc
696 ENDIF ;lasm