title 'Interrupt handler 26 April 87' ; Changes in this module were to remove the 40 column cursor flash ; routine and to add labels to let the code in CXIO change the ; keboard feel and repeat rate. ; ; User assumes _ALL_ liability for it's use. Original copyright is still ; maintained by Commodore maclib z80 maclib cxequ public ?sysint public repeat ; repeat and delay added to allow code public delay ; in CXIO to change repeat and feel of ; keyboard done$scan: equ 11110111b clear$TxD$bit: equ 10010111b ; 2nd byte of res 2,a set$TxD$bit: equ 11010111b ; 2nd byte of setb 2,a buf$end equ low(RxD$buffer+RxD$buf$size) page ; ; The DE register is not changed by the interrupt handler ; ; maximun of T states advaliable per interrupt ; DMA uses about 10 % (or ) leaving only ; interrupt vectoring use a few more. ; ; if both recv$state and send$state are in idle ; T states 209+82++ (191max,38min) = (482max,329min) ; ; ; if ether recv$state and send$state are active ; T states 209+++ (289max, 82min) = (498max,291min) ; CSEG ?sysint: push psw ;11 push b ;11 push h ;11 ; lxi b,CIA$1+int$ctrl ;10 inp a ;12 clear CIA$1 interrupts ; lxi b,CIA2+data$a ;10 inp a ;12 out$rs232$cia equ $+1 setb 2,a ;8 this instruction gets modified outp a ;12 inr c ;4 point to data$b (C=1) inp a ;12 mov h,c ;4 set H=1 recv$state: call recv$idle ;17+(153max,54min) send$state: call send$idle ;17+(136max,28min) dcr h ;4 did H=1 ? lxi h,current$key$delay ;10 jnz skip$keyboard ;10 page ; ; T states 32 if not done ; T states 56+ if key scan done ; vector$key$state: dcr m ;11 jrnz exit$int ;7/12 lda int$rate ;13 mov m,a ;7 key$state: call key$scan$state ;17+(191max,38min) db 21h ; lxi h,(mvi m,1) skip$keyboard: mvi m,1 ; exit$int: pop h pop b pop psw ei ret RxD$count: db 0 ; number of bits left to receive TxD$count: db 0 ; number of bits left to transmit current$key$delay: db 1 page ; ; T states 52 start bit ; T states no start bit, que inactive ; T states no start bit, que active, DAV set ; T states no start bit, que active, DAV cleared ; recv$idle: rar ;4 jrnc set$test$start$bit ;7/(12+36) ;11+12+31=54 ; RxD$unque: ;(36)+12+(105) = 153 max jr test$que ;12 ; ; T states 31 no process required ; T states 91 que count adjusted (not empty) ; t states 105 que count adjusted (empty) ; test$que: lda RS232$status ;13 no processing req if QUE ani 00100000b ;7 bit (5) is clear rz ;5/11 mvi a,que$to$data-test$que ;7 sta RxD$unque+1 ;13 set next sub state lxi h,RxD$buf$get ;10 inr m ;11 mov a,m ;7 cpi buf$end ;7 rnz ;5/11 mvi m,low(RxD$buffer) ;10 ret ;10 ; set$test$start$bit: lxi h,test$start$bit ;10 shld recv$state+1 ;16 ret ;10 page ; ; T states 28 if DAV still set ; T states 89 to move char from que to recv$data ; que$to$data: lda RS232$status ;13 rrc ;4 rc ;5/11 lxi h,RxD$buf$get ;10 mov l,m ;7 mov a,m ;7 sta recv$data ;13 mvi a,adjust$cnt-test$que ;7 sta RxD$unque+1 ;13 set next sub state ret ;10 ; ; T states 82 count not zero ; T states 99 count becomes zero ; adjust$cnt: xra a ;4 lxi h,RxD$buf$count ;10 dcr m ;11 mvi l,low(RS232$status) ;7 setb 0,m ;15 set DAV flag jrnz adj$cont ;7/12 res 5,m ;15 que empty turn QUE bit(5) off mvi a,que$empty-test$que ;7 adj$cont: sta RxD$unque+1 ;13 ret ;10 ; ; T states 52/94 ; que$empty: xra a ;4 offset of zero for JR sta RxD$unque+1 ;13 (to get to test$que) lxi h,xon$xoff$flag ;10 mvi a,XON ;7 cmp m ;7 rz ;5/11 mov m,a ;7 mvi a,send$x-send$norm ;7 sta send$idle+1 ;13 ret ;10 page ; ; test for false start ; ; T states 72 if valid start ; T states 52 if false start ; test$start$bit: rar ;4 jrc set$recv$idle ;7/(12+36) RxD in carry bit lxi h,RS232$status ;10 setb 1,m ;15 set receiving data flag lxi h,start$idle$1 ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 36 ; set$recv$idle: lxi h,recv$idle ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 93 ; start$idle$1: xra a ;4 sta recv$bit+2 ;13 lda XxD$config ;13 ani 1 ;7 adi 7 ;7 sta RxD$count ;13 lxi h,que$full$test ;10 shld recv$state+1 ;16 ret ;10 page ; ; T states 57 RxD buffer not full ; T states 117 RxD buffer full (send XOFF) ; T states 86 RxD buffer full (XOFF sent already) ; que$full$test: lxi h,recv$bit ;10 shld recv$state+1 ;16 lda RxD$buf$count ;13 cpi RxD$buf$size-16 ;7 rc ;5/11 lxi h,xon$xoff$flag ;10 mvi a,XOFF ;7 cmp m ;7 rz ;5/11 mov m,a ;7 set mode to send Xoff mvi a,send$x-send$norm ;7 sta send$idle+1 ;13 ret ;10 ; ; T states 64 ; recv$bit: rar ;4 mvi a,00 ;7 RxD in carry bit rar ;4 move data bit into MSB sta recv$bit+2 ;13 lxi h,recv$bit$done$test ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 69 if bits still remaining ; T states ; recv$bit$done$test: lxi h,RxD$count ;10 dcr m ;11 jrnz enter$recv$bit$idle ;7/(12+36) lda XxD$config ;13 rlc ;4 lxi h,enter$RxD$stop ;10 jrnc do$test$stop ;7/12 lxi h,enter$RxD$parity ;10 do$test$stop: shld recv$state+1 ;16 ani 1*2 ;7 A=0 if 7 bits else 8 bits lda recv$bit+2 ;13 jrnz done$adj ;7/12 rrc ;4 done$adj: sta RxD$data ;13 ret ;10 ; ; T states 36 ; enter$recv$bit$idle: lxi h,recv$bit$idle ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 36+(28/105) ; recv$bit$idle: lxi h,recv$bit ;10 shld recv$state+1 ;16 jmp RxD$unque ;10 page ; ; T states 36+(28/105) ; enter$RxD$parity: lxi h,test$RxD$parity ;10 shld recv$state+1 ;16 jmp RxD$unque ;10 ; ; T states bit hi ; T states bit low ; test$RxD$parity: lxi h,RxD$parity$idle ;10 RxD data bit in carry shld recv$state+1 ;16 rar ;4 lda XxD$config ;13 jrc RxD$parity$hi ;7/12 rlc ;4 rlc ;4 mark space mode ? jrnc test$parity$space ;7/(12+15/46) yes, go test it rlc ;4 get odd even mode jr test$odd$even ;12+35/54 ; test$parity$space: ;15/ rlc ;4 rnc ;5/11 jr parity$error ;12+25 ; test$parity$mark: ;15/ rlc ;4 rc ;5/11 jr parity$error ;12+25 page ; RxD$parity$hi: ;4 rlc ;4 rlc ;4 mark/space mode ? jrnc test$parity$mark ;7/12 yes, go test it rlc ;4 get odd/even flag cmc ;4 toggle it test$odd$even: ;35/ lda recv$bit+2 ;13 aci 0 ;7 ana a ;4 rpe ;5/11 parity$error: ;35 lxi h,RS232$status ;10 setb 4,m ;15 set parity error ret ;10 ; ; T states 36 ; RxD$parity$idle: lxi h,enter$RxD$stop ;10 shld recv$state+1 ;16 jmp RxD$unque ;10 page ; ; T states 90 if que not in use and DAV is cleared ; T states 149/151 if data placed in que ; enter$RxD$stop: lda RS232$status ;13 ani 00100001b ;7 DAV set or data in que? jrnz place$in$que ;7/12 yes, place new char in que lda RxD$data ;13 no, place char in data reg. sta recv$data ;13 lxi h,test$RxD$stop$dav ;10 shld recv$state+1 ;16 ret ;10 ; place$in$que: ;116/118 lxi h,RxD$buf$count ;10 inr m ;11 inr l ;4 mov a,m ;7 inr a ;4 cpi buf$end ;7 jrnz put$buf$ok ;7/12 mvi a,low(RxD$buffer) ;7 put$buf$ok: mov m,a ;7 mov l,a ;4 RxD$data equ $+1 mvi a,00 ;7 mov m,a ;7 lxi h,test$RxD$stop$que ;10 shld recv$state+1 ;16 ret page ; ; T states no errors ; T states framing error ; test$RxD$stop$que: rar ;4 mvi a,00100000b ;7 jmp test$RxD$cont ;10 ; ; T states no errors ; T states framing error ; test$RxD$stop$dav: rar ;4 mvi a,00000001b ;7 test$RxD$cont: jrc good$RxD$stop ;7/12 ori 00001000b ;7 set framing error good$RxD$stop: lxi h,RS232$status ;10 ora m ;7 ani 11111101b ;7 clear recv active flag bit mov m,a ;7 lxi h,recv$idle ;10 shld recv$state+1 ;16 ret ;10 page ;* ;* T states stay in idle state ;* T states exit idle state (recv buffer not full) ;* T states exit idle state (recv buffer full) ;* send$idle: jr send$norm ;12 send$norm: lda RS232$status ;13 rlc ;4 rnc ;5/11 lxi h,start$send$1 ;10 shld send$state+1 ;16 mvi a,clear$TxD$bit ;7 sta out$rs232$cia ;13 send the start bit ret ;10 ; ; T states 12+118 ; send$x: xon$xoff$flag equ $+1 mvi a,XON ;7 sta send$bits+1 ;13 xra a ;4 sta send$idle+1 ;13 mvi a,clear$TxD$bit ;7 sta out$rs232$cia ;13 send the start bit lxi h,RS232$status ;10 setb 6,m ;15 flag send bussy lxi h,start$xon$xoff ;10 shld send$state+1 ;16 ret ;10 page ; ; T states 107 ; start$send$1: lda xmit$data ;13 sta send$bits+1 ;13 lxi h,RS232$status ;10 mov a,m ;7 xri 0C0h ;7 clear bit 7 and set bit 6 mov m,a ;7 start$xon$xoff: lda XxD$config ;13 ani 1 ;7 adi 7 ;7 sta TxD$count ;13 enter$send$bits: lxi h,start$bit$idle ;10 shld send$state+1 ;16 ret ;10 ; ; T states 36 ; start$bit$idle: lxi h,send$bits ;10 shld send$state+1 ;16 ret ;10 ; ; T states 94 data bit low ; T states 92 data bit hi ; send$bits: mvi a,00 ;7 rrc ;4 sta send$bits+1 ;13 lxi h,count$TxD ;10 shld send$state+1 ;16 send$TxD: ;42/44 mvi a,set$TxD$bit ;7 jrc send$hi$bit ;7/12 mvi a,clear$TxD$bit ;7 send$hi$bit: sta out$rs232$cia ;13 ret ;10 ; ; T states if more data bits to send ; T states if done sending bits ; count$TxD: lxi h,TxD$count ;10 dcr m ;11 jrnz enter$send$bits ;7/12 lxi h,TxD$parity$wait ;10 shld send$state+1 ;16 ret ;10 page ; ; T states 36 ; TxD$parity$wait: lxi h,TxD$parity ;10 shld send$state+1 ;16 ret ;10 ; ; ; T states 85 if no parity ; T states 124 if mark parity ; T states 126 if space parity ; T states 136 if even parity ; T states 129 if odd parity ; TxD$parity: lda XxD$config ;13 rlc ;4 jrnc TxD$stop ;7/(12+56) lxi h,TxD$parity$idle$1 ;10 shld send$state+1 ;16 rlc ;4 jrnc send$mark$space ;7/(12+16+42/44) rlc ;4 lda send$bits+1 ;13 aci 0 ;7 ana a ;4 mvi a,set$TxD$bit ;7 jpo send$TxD$parity ;10 mvi a,clear$TxD$bit ;7 send$TxD$parity: sta out$rs232$cia ;13 ret ;10 ; send$mark$space: rlc ;4 jr send$TxD ;12+42/44 ; ; T states 36 ; TxD$parity$idle$1: lxi h,TxD$parity$idle$2 ;10 shld send$state+1 ;16 ret ;10 ; ; T states 36 ; TxD$parity$idle$2: lxi h,TxD$stop ;10 shld send$state+1 ;16 ret ;10 page ; ; T states 103/101 ; TxD$stop: lxi h,TxD$stop$idle ;10 shld send$state+1 ;16 mvi a,set$TxD$bit ;7 sta out$rs232$cia ;13 lda XxD$config ;13 ani 2 ;7 jrnz one$stop$bit ;7/12 mvi a,5 ;7 one$stop$bit: inx h ;6 mov m,a ;7 ret ;10 ; ; T states 35/90 ; TxD$stop$idle: mvi a,00 ;7 dcr a ;4 sta TxD$stop$idle+1 ;13 rnz ;5/11 lxi h,RS232$status ;10 res 6,m ;15 lxi h,send$idle ;10 shld send$state+1 ;16 ret ;10 page ; ; ; Key$Scan$State: jr scan$CIA ;12 ; ; T states no new key down ; T states state change ; T states new key down ; scan$CIA: stc ;4 mvi a,11111110b ;7 data field updated by code lxi b,key$row ;10 outp a ;12 cpi 11111111b ;7 jrz extra$3 ;7/12 carry=0 if A=11111111 ral ;4 sta scan$CIA+1+1 ;13 lxi h,key$scan$tbl ;10 get current new table pointer inr c ;4 point to KEY$COL (input) jmp cont$read ;10 ; extra$3: ral ;4 sta scan$CIA+1+1 ;13 mvi a,scan$VIC-scan$CIA ;7 sta Key$Scan$State+1 ;13 ret ;10 page ; ; T states no new key and no state change ; scan$VIC: mvi a,11101110b ;7 lxi h,key$scan$tbl ;10 get current new table pointer lxi b,vic$key$row ;10 outp a ;12 rlc ;4 sta scan$VIC+1 ;13 jrnc normal$8 ;7/12 lxi b,key$col ;10 cont$read: inp a ;12 0FFh if no key down inr m ;11 mov l,m ;7 mov b,m ;7 get old value in B mov m,a ;7 save new value xra b ;4 get differances ana b ;4 test for only new keys down rz ;5/11 sta matrix$byte ;13 lxi h,key$found ;10 shld key$state+1 ;16 ret ;10 ; ; normal$8: ; mvi a,scan$CIA-scan$CIA ;7 xra a ;4 sta Key$Scan$State+1 ;13 mov m,l ;7 reset current table pointer lxi h,Key$Repeat$State ;10 shld key$state+1 ;16 ret ;10 page ; ; T states 48 repeat not active ; T states 124 testing repeat (key realeased) ; T states 110 testing repeat (not found) ; T states 109 testing repeat (found) ; Key$Repeat$State: lxi h,Key$Scan$State shld key$state+1 ;16 repeat$count equ $+1 mvi a,00 ;7 ora a ;4 rz ;5/11 lxi h,repeat$count ;10 dcr a ;4 yes, test for repeat yet jrnz not$repeat$yet ;7/(12+(42/56)) ; ; the following 4 lines of code may NOT be changed. ; CONF.COM looks for them to change the repeat rate. ; also looks for RET ; MVI A,xx ; STA xxxx (see set$key$parm) repeat equ $+1 mvi m,3 ;10 lxi h,save$key ;10 shld key$state+1 ;16 ret ;10 ; not$repeat$yet: ;42/56 mov m,a ;7 matrix$pos equ $+1 lda Key$scan$tbl ;13 repeat$mask equ $+1 mvi b,00 ;7 ana b ;4 key still down? (A=0) rz ;5/11 yes, exit for now mvi m,0 ;10 ret ;10 page ; ; ; ; ; key$found: ;148/138/157/147/166/156/161/167 matrix$byte equ $+1 mvi b,00 ;7 mov a,b ;4 ani 11110000b ;7 jz check$low$4 ;10+(138/128/133/139) ani 11000000b ;7 jrz check$5$and$4 ;7/(12+(110/100)) ani 10000000b ;7 mvi c,6 ;7 jrnz is$add$1 ;7/(12+70) mvi a,01000000b ;7 jr is$common ;12+66 ; check$5$and$4: ;110/100 mov a,b ;4 ani 00100000b ;7 mvi c,4 ;7 jrnz is$add$1 ;7/(12+70) mvi a,00010000b ;7 jr is$common ;12+66 ; ; check$low$4: ;138/128/133/139 mov a,b ;4 ani 00001111b ;7 jrz exit$found ;7/12 ani 00001100b ;7 jrz check$1$and$0 ;7/12+(96/102) ani 00001000b ;7 mvi c,2 ;7 jrnz is$add$1 ;7/(12+70) mvi a,00000100b ;7 jr is$common ;12+66 ; check$1$and$0: ; mov a,b ;4 ani 00000010b ;7 mvi c,0 ;7 jrnz is$add$1 ;7/(12+70) inr a ;4 set A=1 jr is$common ;12+66 ; ; is$add$1: ;70 inr c ;4 is$common: ;66 sta mask$value ;13 mov a,c ;4 sta bit$value ;13 lxi h,key$found$2 ;10 shld key$state+1 ;16 ret ;10 ; exit$found: lxi h,Key$Scan$state ;10 shld key$state+1 ;16 ret ;10 page ; ; T states ; key$found$2: lxi h,matrix$byte ;10 mask$value equ $+1 mvi a,00 ;7 xra m ;7 clear current bit mov m,a ;7 bit$value equ $+1 mvi b,00 ;7 lxi h,key$scan$tbl ;10 get the pointer mov a,m ;7 sub l ;4 remove the bias dcr a ;4 then one extra (pointer) add a ;4 add a ;4 add a ;4 shift left 3 bits add b ;4 add in bit position sta key$code ;13 save as the key code lxi h,remove$special$keys ;10 shld key$state+1 ;16 ret ;10 page ; ; T states if not a shift of control key ; T states 68/82/96 if cntr / rt_shift / lf_shift ; remove$special$keys: lxi h,key$found ;10 lda key$code ;13 cpi 38h+2 ;7 control key pressed ? jrz bad$key ;7/12 cpi 30h+4 ;7 jrz bad$key ;7/12 cpi 08h+7 ;7 jrz bad$key ;7/12 lxi h,set$key$parm ;10 bad$key: shld key$state+1 ;16 ret ;10 ; ; T states ; ; do not change the next 2 lines. CONF uses them to ; the set repeat rate. (also RET above here) ; delay equ $+1 set$key$parm: mvi a,8 ;7 sta repeat$count ;13 number of counts for repeat lda key$scan$tbl ;13 sta matrix$pos ;13 lda mask$value ;13 sta repeat$mask ;13 lxi h,build$cntr$byte ;10 shld key$state+1 ;16 ret ;10 ; ; T states ; build$cntr$byte: lda key$scan$tbl+1+7 ;13 get control byte row cma ;4 ani 04h ;7 test control key bit jrz not$control ;7/12 mvi a,7 ;7 not$control: mov b,a ;4 lda key$scan$tbl+1+6 ;13 get rigth shift byte row cma ;4 ani 10h ;7 test right key bit ora b ;4 mov b,a ;4 lda key$scan$tbl+1+1 ;13 get left shift byte row cma ;4 ani 80h ;7 test left key bit ora b ;4 mov b,a ;4 ani 90h ;7 either shift key down? mov a,b ;4 jrz no$shift ;7/12 no, jump ori 2 ;7 yes, set shift control bit no$shift: sta ctrl$byte ;13 lxi h,save$key ;10 shld key$state+1 ;16 ret ;10 page ; ; ; NOTE: character buffer MUST be on one page ; (and have even number of bytes) ; ; buffer is FULL when data at put pointer does not equal 0ffh ; insert new character at (put pointer) ; and character control byte at (put pointer)+1 ; ; T states 38 if buffer is full ; T states 146/148 ; save$key: lhld key$put$ptr ;16 get put pointer mov a,m ;7 get byte from buffer inr a ;4 room in buffer? (-1 if so) rnz ;5/11 no, wait for room in buffer key$code equ $+1 mvi m,00 ;10 get matrix position inr l ;4 ctrl$byte equ $+1 mvi a,00 ;7 mov m,a ;7 inr l ;4 mov a,l ;4 cpi low(key$buffer+key$buf$size) ;7 jrnz put$ptr$ok ;7/12 mvi a,low(key$buffer) ;7 put$ptr$ok: sta key$put$ptr ;13 adjust the low byte of the put ptr lxi h,Key$tick ;10 shld key$state+1 ;16 ret ;10 ; ; T states ; key$tick: lxi b,sid+24 ;10 lda tick$vol ;13 outp a ;12 mvi c,low(sid+11) ;7 mvi a,80h ;7 outp a ;12 inr a ;4 outp a ;12 lxi h,key$scan$state ;10 shld key$state+1 ;16 ret ;10 page ; ;_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ __________ ; | | | | | | | | | | | | | ; | S | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | P | stop | ; |_____|_____|_____|_____|_____|_____|_____|_____|_____|_____| | |_ ; ; ; Reciever State Machine ; ; ;_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ __________ ; | | | | | | | | | | | | | ; | S | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | P | stop | ; |_____|_____|_____|_____|_____|_____|_____|_____|_____|_____| | |_ ; ; ; Transmitter State Machine (TSM) ; ; ; ; Keyboard Scan State Machine (KSSM) ;