page 200 ; Interrupt drivers for ASCI0 and ASCI1 global as0init global as0ista,as0inp global as0osta,as0out global as1init global as1ista,as1inp global as1osta,as1out extrn as_init extrn ff_empty,ff_get,ff_full,ff_put extrn ff_puth,ff_cnt,ff_gech extrn bufinit extrn isv_sw include config.inc include z180reg.inc ;----------------------------------------------------- dseg mkbuf s0.rx_id, s0.inbuf, s0.rx_len mkbuf 0, s0.instatbuf, s0.rx_len mkbuf s0.tx_id, s0.outbuf,s0.tx_len mkbuf s1.rx_id, s1.inbuf, s1.rx_len mkbuf 0, s1.instatbuf, s1.rx_len mkbuf s1.tx_id, s1.outbuf,s1.tx_len dseg ;-------------------------------------------------------------- ; Init Serial I/O for input and output (ASCI 0/1) ; ; b: device number ; ;ser.init: ; ld a,i ; push af ;save IFF ; di ;--- ; pop af ; ret po ; ei ; ret ; as0init: xor a ; out0 (stat0),a ;Disable rx/tx interrupts ld c,0 ;asci channel number call as_init ld hl,rtxisvjmp0 ;rx/tx int vector ld (ivtab + IV$ASCI0),hl ; ld ix,s0.inbuf call bufinit ld ix,s0.outbuf call bufinit ld a,M_RIE out0 (stat0),a ;Enable rx interrupts ret as1init: xor a ; out0 (stat1),a ;Disable rx/tx interrupts ld c,1 ;asci channel number call as_init ld hl,rtxisvjmp1 ;rx/tx int vector ld (ivtab + IV$ASCI1),hl ; push ix ld ix,s1.inbuf call bufinit ld ix,s1.outbuf call bufinit pop ix ld a,M_RIE out0 (stat1),a ;Enable rx interrupts ret cseg rtxisvjmp0: call isv_sw dw rxtxi0 rtxisvjmp1: call isv_sw dw rxtxi1 ;-------------------------------------------------------------- dseg as0ista: push ix ld ix,s0.inbuf ; call ff_empty pop ix ret ;-------------------------------------------------------------- as1ista: push ix ld ix,s1.inbuf ; call ff_empty pop ix ret ;-------------------------------------------------------------- ; Get an input character as0inp: push ix ld ix,s0.inbuf ; call ff_gech ld a,b cp s0.rx_len/4 jr nc,a0i_1 di in0 a,(cntla0) and ~M_RTS0 ;assert RTS or M_EFR ;don't reset error flags ei out0 (cntla0),a a0i_1: ld a,c pop ix ret ;-------------------------------------------------------------- ; Get an input character as1inp: push ix ld ix,s1.inbuf ; call ff_gech pop ix ret ;-------------------------------------------------------------- ; Output status as0osta: push ix ld ix,s0.outbuf ; call ff_full pop ix ret ;-------------------------------------------------------------- ; Output status as1osta: push ix ld ix,s1.outbuf ; call ff_full pop ix ret ;-------------------------------------------------------------- ; put character in c in buffer ; destroys hl, bc ; returns output char in a as0out: push ix ; ld ix,s0.outbuf ; call ff_puth pop ix ; di ; in0 c,(stat0) ; set TIE,c ; out0 (stat0),c ; ei ; ret ;-------------------------------------------------------------- ; put character in c in buffer ; destroys hl, bc ; returns output char in a as1out: push ix ; ld ix,s1.outbuf ; call ff_puth pop ix ; di ; in0 c,(stat1) ; set TIE,c ; out0 (stat1),c ; ei ; ret ;------------------------------------------ ; ASCI 0 Transmit/Receive interupt routines dseg rxtxi0: push ix rxtxi0_loop: in0 e,(stat0) ;receive flag set? jp p,rxtxi0_1 ;RDRF == Bit 7 rxi_0 in0 a,(asext0) ;todo: break detection and M_BREAK or e ld e,a in0 d,(cntla0) ; res EFR,d ; ld ix,s0.inbuf ; ld c,(ix+o.in_idx) ; ld b,0 ld hl,s0.inbuf ; add hl,bc in0 a,(rdr0) ; ld (hl),a ld hl,s0.instatbuf ;save error status add hl,bc ld (hl),e ;todo: error handling and break detection ld a,c ;increment buffer in pointer inc a ; ld b,(ix+o.mask) ; and b ; ld c,a sub (ix+o.out_idx) ; jr z,$+5 ;skip if buffer is full ld (ix+o.in_idx),c ; jr nc,$+3 ; adc b ; cp s0.tx_len*3/4 jr c,$+4 set RTS0,d ;RTS inactive ?0ri_1: out0 (cntla0),d ; jr rxtxi0_loop rxtxi0_1: bit TDRE,e ;TX int? jr z,rxtxi0_e ; ld ix,s0.outbuf ; ld a,(ix+o.out_idx) ; cp (ix+o.in_idx) ;if index.in == index.out jr z,?0ti_2 ; buffer empty ld hl,s0.outbuf ; ld c,a ld b,0 add hl,bc ld b,(hl) out0 (tdr0),b ; 7 inc a and (ix+o.mask) ld (ix+o.out_idx),a jr rxtxi0_loop ?0ti_2: res TIE,e ;disable tx-int out0 (stat0),e ; 5 rxtxi0_e: pop ix ret ;------------------------------------------ ; ASCI 1 Transmit/Receive interupt routines dseg rxtxi1: in0 e,(stat1) ;receive flag set? 5 jp p,txi1_0 ; in0 d,(rdr1) ;todo: break detection 9 bit FE,e ;framing error? jr nz,??ri_1 push ix ld ix,s1.inbuf ; ld hl,s1.inbuf ; ld c,(ix+o.in_idx) ; ld b,0 add hl,bc ld (hl),d ld a,c ; inc a and (ix+o.mask) cp (ix+o.out_idx) ; jr z,$+5 ;skip if buffer is full ld (ix+o.in_idx),a pop ix ??ri_1: in0 a,(cntla1) ; 1 res EFR,a ; out0 (cntla1),a ; 1 ret txi1_0: push ix ld ix,s1.outbuf ; ld a,(ix+o.out_idx) ; cp (ix+o.in_idx) ;if index.in == index.out jr z,??ti_2 ; buffer empty ld hl,s1.outbuf ; ld c,a ld b,0 add hl,bc ld l,(hl) out0 (tdr1),l ; 7 inc a and (ix+o.mask) ld (ix+o.out_idx),a jr ??ti_3 ??ti_2: res TIE,e ;disable tx-int out0 (stat1),e ; 5 ??ti_3: pop ix ret end