title 'Character I/O handler for Jonos LTD. computers' ; ; character I/O for CP/M 3.0 ; ; please not that 19200 baud will not work in most cases ; with a 4mhz CPU card, but will with a 6mhz card ; all other rates will work, see table for % error ; true equ -1 ;set value true false equ not true ;set value false ; CPU$4mhz equ false ;CPU speed CPU$6mhz equ not CPU$4mhz ;for baud rate divisor table ; public ?cinit,?ci,?co,?cist,?cost public @ctbl ; maclib Z80 ;z80 opcodes used maclib ports ;need port address maclib modebaud ;define mode bits and baud equates ; parity$mask equ 07fh ;parity mask (change to 0ffh for none) max$devices equ 4 ;CRT,MODEM,TERMINAL,PARALLEL ports ; cseg ;code to be in commom memory for banked ; ; character device initialization ; ?cinit: mov a,c ;get device # cpi max$devices ;see if in range rnc ;return if not in range ora a ;see if CRT controller rz ;CRT controller need no initialization cpi 01h ;printer (termainl port) jz ter$port$init ;set up terminal port cpi 02h ;see if modem port jz mod$port$init ;set up terminal port ret ;must be parallel port ; baud$add: mvi h,0 ;make device address 16 bit mov l,c ; dad h! dad h! dad h! ;*8 (lenght of each entry ctbl) lxi d,@ctbl+7 ;point to baud rate dad d ; mov a,m ;get baud rate ani 0fh ;only need lower nible mov l,a ;put in l mvi h,0 ;zero hl dad h ;*2 lxi d,baud$divisor ;point to baud rate divisor table dad d ;get address of baud rate mov e,m ;get lsb inx h ;next byte mov d,m ;get msb ret ;return with baud rate divisor in ; ter$port$init: mvi a,36h ;set mode port square wave out cnt$md ;output for counter 0 call baud$add ;get baud rate divisor mov a,e ;get lsb divisor out cnt$0 ;output mov a,d ;get msb divisor out cnt$0 ;output ret ;return ; mod$port$init: mvi a,76h ;set mode port square wave out cnt$md ;output for counter 1 call baud$add ;get baud rate divisor mov a,e ;get lsb divisor out cnt$1 ;output mov a,d ;get msb divisor out cnt$1 ;output ret ;return ; ; character device input routine ; ?ci: mov a,b ;get device # cpi max$devices-1 ;see if in range (can`t read parallel) jnc null$input ; ci1: call ?cist ;input status jz ci1 ;wait for character ready mov a,b ;get device # ora a ;set flags jz crt$in ;if crt controller jump cpi 01h ;see if terminal port jz ter$port$in ;input character form terminal mod$port$in: in uart$a$d ;input character from modem port ani parity$mask ;mask parity ret ;return with character in ter$port$in: in uart$b$d ;input character from termianl port ani parity$mask ;mask parity ret ;return with character in crt$in: in crt$0$d ;input character from terminal port ani parity$mask ;mask parity ret ; null$input: mvi a,1ah ;see end of file character ret ; ; character device input status ; ?cist: mov a,b ;get device # cpi max$devices-1 ;see if in range jnc null$status ;can`t read from device ora a ;set flags jz crt$in$status ;read input status crt controller cpi 01h ;see if termainl port jz ter$in$status ;read input status termianl port mod$in$status: in uart$a$s ;input modem port status jmp cist1 ;use common routine ter$in$status: in uart$b$s ;input terminal port status jmp cist1 ;use common routine crt$in$status: in crt$0$s ;input crt controller status cist1: ani 02h ;mask rxrdy bit rz ;return with 0 no character mvi a,0ffh ;load status for character ready ret ;ret ; null$status: xra a ;zero ret ; ; ; character device output ; ?co: mov a,b ;get device # cpi max$devices ;see if in range rnc ;null output co1: call ?cost ;get output status jz co1 ;loop till ready to output mov a,b ;get device # ora a ;see if crt jz crt$out ;jump if crt cpi 01h ;see if terminal port jz ter$out ;output if is cpi 02h ;see if modem port jz mod$out ;output if is parallel$out: mov a,c ;get character out pt$1 ;output it ret mod$out: mov a,c ;get character out uart$a$d ;output it ret ter$out: mov a,c ;get character out uart$b$d ;output it ret crt$out: mov a,c ;get character out crt$0$d ;output it ret ; ; character device output status ; ?cost: mov a,b ;get device # cpi max$devices ;see if in range jnc null$status ; ora a ;set flags jz crt$out$status ;see if crt controller cpi 01h ;see if terminal port jz ter$out$status ; cpi 02h ;see if modem port status jz mod$out$status ; parallel$status: in pt$1 ;get status jmp cist1 ;jmp common code mod$out$status: in uart$a$s ;input status jmp cost2 ;jump to common code ter$out$status: in uart$b$s ;input status cost2: ani 05h ;mask txrdy and txemty rar ;test bit jnc cost1 ;jump if not ready ora a ;set flags jz cost1 ;jump if not ready mvi a,0ffh ;set status ready ret cost1: xra a ;zero a and set zero flag ret ;return status not ready crt$out$status: in crt$0$s ;input status ani 01h ;mask txrdy bit rz ;return not ready mvi a,0ffh ;set status ready ret ; ; ; baud rate divisor table ; baud$divisor: ; divisor rate % error if cpu$4mhz b0 dw 0 ;no baud rate b50 dw 2500 ;50 0 b75 dw 1667 ;75 .02 b110 dw 1136 ;110 .03 b134 dw 923 ;134.5 .05 b150 dw 833 ;150 .04 b300 dw 417 ;300 .08 b600 dw 208 ;600 .16 b1200 dw 104 ;1200 .16 b1800 dw 69 ;1800 .64 b2400 dw 52 ;2400 .16 b3600 dw 35 ;3600 .79 b4800 dw 26 ;4800 .16 b7200 dw 17 ;7200 2.12 b9600 dw 13 ;9600 .16 b19200 dw 7 ;19200 6.99 endif ; if cpu$6mhz b0 dw 0 ;no baud rate b50 dw 3750 ;50 0 b75 dw 2500 ;75 0 b110 dw 1705 ;110 .02 b134 dw 1384 ;134.5 .01 b150 dw 1250 ;150 0 b300 dw 625 ;300 0 b600 dw 313 ;600 .15 b1200 dw 156 ;1200 .16 b1800 dw 104 ;1800 .16 b2400 dw 78 ;2400 .16 b3600 dw 52 ;3600 .16 b4800 dw 39 ;4800 .16 b7200 dw 26 ;7200 .16 b9600 dw 20 ;9600 2.34 b19200 dw 10 ;19200 2.34 endif ; ; character device table ; @ctbl: db 'INTCRT' ;device 0, internal CRT db mb$in$out db baud$none db 'TERM ' ;device 1, termianl port (nornal printer) db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'MODEM ' ;device 2, modem port db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CEN ' ;device 3, parallel printer port db mb$output db baud$none db 0 ;table terminator ; end