(************* UNIT KERMACIA ********************************************) (*$S+*) (*$I-*) (*$R-*) (*$V-*) UNIT KERMACIA; intrinsic code 18 data 19; INTERFACE USES kermglob; PROCEDURE send_break ( adr_comm_reg : integer ); PROCEDURE get_acia_parms( var xpar : parity_type; var xdbit, xstopbit, xbaud : integer ); PROCEDURE set_acia_parms( xpar : parity_type; xdbit, xstopbit, xbaud : integer ); IMPLEMENTATION This unit implements the possibility to change baud rates, parity, number of databits and stopbits for outgoing characters and the possibility to send a break signal to the remote host. This unit is dependent on a special unitstatus call, provided by the attached driver for remin: ( see file remdriver.text ). The code below is specific for the 6551 acia on a AP2 serial card from IBS and for the 6850 acia on a CCS model 7710 ASI1 card, that is probably similar to the Apple Com Card and the Hayes micromodem card. On the CCS card it is not possible to change the baud rate by soft command nor is it possible to set space parity. If you have a different serial card then this unit should be adapted to the requirements of that card's acia. If you do not know how to or do not want to rewrite this unit's implementation, then you can set the value of 'acia_implem' in the kermit.data file to 0 (= unknown). The settable parameters will then equal the default values , but can no longer be changed at run time. The procedure send_break will then do nothing. acia_cntrl_reg = -16209; =$C0AF Specific for a 6551 acia on a acia_comm_reg = -16210; =$C0AE AP2 serial card in slot 2. acia_comm_reg = -16224; =$C0A0 Specific for CCS 6850 acia. The 6850 does not have a control register. These 2 adresses are declared in unit kermglob. If your card also has a 6551 acia then these adresses will probably be different. They can then be changed in the kermit.data file. TYPE baud_types = (B16ext, B50, B75, B110, B135, B150, B300, B600, B1200, B1800, B2400, B3600, B4800, B7200, B9600, B19200); { 6551 specific } dbit_types = (dbit8, dbit7, dbit6, dbit5 ); { 6551 specific } cntrl_6551 = PACKED RECORD baudr : baud_types; freq : ( ext, int ); wordlen: dbit_types; stpbit : ( one, variable ); msb1 : 0..255 ; END; comm_6551 = PACKED RECORD dont_change : 0..31 ; set_par : BOOLEAN; par_type : ( p_odd, p_even, p_mark, p_space ); msb2 : 0..255 ; END; comm_6850 = PACKED RECORD filler1 : 0..3 ; serdata : ( d7pes2, d7pos2, d7pes1, d7pos1, d8pns2, d8pns1, d8pes1, d8pos1 ); { d=databits, p=parity, e=even, o=odd, n=none, s=stopbit } filler2 : 0..7 ; msb3 : 0..255; END; stat_rec1 = RECORD adres1 : INTEGER; content1 : cntrl_6551; END; stat_rec2 = RECORD adres2 : INTEGER; content2 : comm_6551; END; stat_rec3 = RECORD adres3 : INTEGER; content3 : comm_6850; END; VAR baud_rate : ARRAY[ baud_types ] OF INTEGER; dbits : ARRAY[ dbit_types ] OF INTEGER; reg_6551_control : stat_rec1; reg_6551_komm : stat_rec2; reg_6850_comm : stat_rec3; cw_status, cw_control : cntrl_word_rec; PROCEDURE get_6551_parms ( var xpar:parity_type; var xdbit, xstopbit, xbaud : integer ); BEGIN reg_6551_control.adres1 := acia_cntrl_reg; reg_6551_komm.adres2 := acia_comm_reg; UNITSTATUS( inport, reg_6551_control, cw_status ); UNITSTATUS( inport, reg_6551_komm, cw_status ); WITH reg_6551_komm.content2 DO BEGIN IF set_par THEN BEGIN CASE par_type OF p_odd : xpar := odd_par; p_even : xpar := even_par; p_mark : xpar := mark_par; p_space : xpar := space_par; END; END ELSE xpar := no_par; END; { with } WITH reg_6551_control.content1 DO BEGIN xbaud := baud_rate[ baudr ]; xdbit := dbits[ wordlen ]; CASE stpbit OF one : xstopbit := 1; variable : BEGIN xstopbit := 2; IF ( xpar <> no_par ) and ( word_len = dbit8 ) THEN xstopbit := 1; IF ( xpar = no_par ) and ( word_len = dbit5 ) THEN xstopbit := 15; END; END; { case stpbit } END; { with } END; { get_6551_parms } NOTE : xstopbit = 15 actually means 1.5 stopbit PROCEDURE get_acia_parms{ var xpar:parity_type; var xdbit,xstopbit,xbaud : integer}; begin if acia_implem = A6551 then get_6551_parms( xpar, xdbit, xstopbit, xbaud ); end; { get_acia_parms } PROCEDURE set_6551_parms ( xpar:parity_type; xdbit, xstopbit, xbaud : integer ); VAR oldpar : parity_type; oldbaud, olddbit, oldstopb : INTEGER; i : baud_types; j : dbit_types; BEGIN get_6551_parms( oldpar, olddbit, oldstopb, oldbaud ); WITH reg_6551_komm.content2 DO BEGIN set_par := TRUE; CASE xpar OF no_par : set_par := FALSE; odd_par : par_type := p_odd; even_par : par_type := p_even; mark_par : par_type := p_mark; space_par : par_type := p_space; END; { case } END; { with } UNITSTATUS( inport, reg_6551_komm, cw_control ); WITH reg_6551_control.content1 DO BEGIN FOR i := B50 TO B19200 DO IF baud_rate[ i ] = xbaud THEN baudr := i; FOR j := dbit8 TO dbit5 DO IF dbits[ j ] = xdbit THEN word_len := j; IF xstopbit = 1 THEN stpbit := one ELSE stpbit := variable; END; { with } UNITSTATUS( inport, reg_6551_control, cw_control ); END; { set_6551_parms } PROCEDURE set_6850_parms( xpar:parity_type; xdbit,xstop : integer); BEGIN WITH reg_6850_comm.content3 DO BEGIN IF (xdbit=7) and (xpar=evenpar) and (xstop=1) THEN serdata := d7pes1 ELSE IF (xdbit=7) and (xpar= oddpar) and (xstop=1) THEN serdata := d7pos1 ELSE IF (xdbit=7) and (xpar=evenpar) and (xstop=2) THEN serdata := d7pes2 ELSE IF (xdbit=7) and (xpar= oddpar) and (xstop=2) THEN serdata := d7pos2 ELSE IF (xdbit=8) and (xpar=markpar) and (xstop=1) THEN serdata := d8pns2 ELSE IF (xdbit=8) and (xpar= nopar) and (xstop=1) THEN serdata := d8pns1 ELSE IF (xdbit=8) and (xpar= oddpar) and (xstop=1) THEN serdata := d8pos1 ELSE IF (xdbit=8) and (xpar=evenpar) and (xstop=1) THEN serdata := d8pes1 ELSE EXIT( set_6850_parms ); END; { WITH } reg_6850_comm.content3.filler1 := 3; reg_6850_comm.content3.filler2 := 0; reg_6850_comm.adres3 := acia_comm_reg; UNITSTATUS( inport, reg_6850_comm, cw_control ); { first give an acia master reset } reg_6850_comm.content3.filler1 := 1; UNITSTATUS( inport, reg_6850_comm, cw_control ); { set acia command register to desired value } parity := xpar; stopbit := xstop; databit := xdbit; END; { set_6850_parms } PROCEDURE set_acia_parms { xpar : parity_type; xdbit, xstopbit, xbaud : integer }; begin case acia_implem of A6551 : set_6551_parms( xpar, xdbit, xstopbit, xbaud ); A6850 : set_6850_parms( xpar, xdbit, xstopbit ); end; end; { set_acia_parms } PROCEDURE send_6551_break ( adr_comm_reg : INTEGER ); EXTERNAL; PROCEDURE send_6850_break ( adr_comm_reg : INTEGER ); EXTERNAL; See file asm.acia.text PROCEDURE send_break { adr_comm_reg : integer }; sends a break signal to the host. Signal is shut off by typing any key. The command register is restored to the previous value. begin case acia_implem of A6551 : send_6551_break( adr_comm_reg ); A6850 : begin send_6850_break( adr_comm_reg ); set_acia_parms( parity, databit, stopbit, baud ); end; end; end; { send_break } BEGIN baud_rate[ B16ext ] := 0; baud_rate[ B50 ] := 50; baud_rate[ B75 ] := 75; baud_rate[ B110 ] := 110; baud_rate[ B135 ] := 135; baud_rate[ B150 ] := 150; baud_rate[ B300 ] := 300; baud_rate[ B600 ] := 600; baud_rate[ B1200 ] := 1200; baud_rate[ B1800 ] := 1800; baud_rate[ B2400 ] := 2400; baud_rate[ B3600 ] := 3600; baud_rate[ B4800 ] := 4800; baud_rate[ B7200 ] := 7200; baud_rate[ B9600 ] := 9600; baud_rate[ B19200 ] := 19200; dbits[ dbit8 ] := 8; dbits[ dbit7 ] := 7; dbits[ dbit6 ] := 6; dbits[ dbit5 ] := 5; WITH cw_status DO BEGIN channel := inp; purpose := status; special_req := rw_req; reserved := 0; filler := 0; END; cw_control := cw_status; cw_control.purpose := control; { set serial data for 6850 acia to pascal defaults } parity := no_par; stopbit := 1; databit := 8; END.