SBTTL 'IRQ Handelers and I/O Routines (6_Dec_84)' PAGE ;====================================================================== ; ; Copyright 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; ;---------------------------------------------------------------------- ; Index (12_Nov_84) ;------------------ ; ; IRQVEC Maskable Interrupt Entry ; NMIVEC Non_Maskable Interrupt Entry ; ; SNDINS Insert a Character into the Send Buffer ; SNDREM Remove a Character from the Send Buffer ; ININS Insert a Character into the Input Buffer ; INREM Remove a Character from the Input Buffer ; KEYINS Insert a Character into the Key Buffer ; KEYREM Remove a Character from the Key Buffer ; ; GETKEY Get a Character from the Keyboard ; PUTKEY Put a Character to the Keyboard PAGE ;---------------------------------------------------------------------- ; Maskable Interrupt Entry Point ;------------------------------- ; 1) Irq occurs when the keyboard wants to send a char to the processor ; 2) The FTCHKEY entry is only used by the PUTKEY routine. ; ;PUTKEY Entry Point FTCHKEY:PLA ;Alias an IRQ (so RTI returns properly) TAX INX TXA PHA ;increment the return address by one PHP ;push the status onto the stack ;Normal IRQ Entry Point IRQVEC: PHA ;Save the Registers TYA PHA TXA PHA JSR GETKEY ;Get the key from the keyboard LDY LOCKMD ;If (Keyboard ne Locked) BMI IRQSK1 JSR KEYINS ; Insert Character into the Key Buffer IRQSK1: PLA TAX ;Restore the Registers PLA TAY PLA RTI ;Return PAGE ;---------------------------------------------------------------------- ; Non_Maskable Interrupt Entry Point (6_Dec_84) ;---------------------------------------------- ; 1) This Routine handels interrupts from the UART (ie the host computer ; has sent a character). ; 2) Notice that nulls are ignored unless we're in monitor mode. ; NMIVEC: SEI ;disable interrupts PHA LDA NMIOK ;see if NMI is enabled CMP #$A5 ;(must be A5 to handle interrupts) BNE NMISK3 ;If (Interrupts are Enabled) TYA ; (Save the Index Registers) PHA TXA PHA LDA S1DATA ; Get a Character from the Uart AND #%01111111 ; (Remove the Parity Bit) BNE NMISK1 ; If ( (Char ne 0) Or LDY MONITOR ; (Monitor eq Enabled) ) BEQ NMISK2 NMISK1: JSR ININS ; Insert Char into Input Buffer NMISK2: PLA ; Restore the Registers TAX PLA TAY PLA RTI ; Return NMISK3: LDA S1DATA ;Else clear NMI, and throw away the character PLA RTI ; Return PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Send Buffer (30_Nov_84) ;---------------------------------------------------- ; SNDINS: LDY BRKHIT ;If (BrkHit eq True) BEQ SISK1 CMP #CTRLC ; If (Character to Store eq ^C) BEQ SISK2 ; return LDY #0 ; Else STY BRKHIT ; BRKHIT = FALSE SISK1: LDY OUTEP ;Y:= End Buffer Index INY ;Increment the End Buffer Index CPY OUTSP ;If (The Buffer HAS NOT Overrun) BEQ SISK2 STY OUTEP ; Save the End Buffer Offset STA SNDBUF,Y ; Store the Character SISK2: RTS ;Return ;---------------------------------------------------------------------- ; Remove a Character from the Send Buffer (30_Nov_84) ;---------------------------------------------------- ; SNDREM: LDX OUTSP ;X:= Start Buffer Index CPX OUTEP BNE SRSK1 ;If (The Buffer is Empty) LDA #$FF ; A:= 0FF (Buffer Empty Flag) RTS ; Return SRSK1: INX ;Else Increment the Start Buffer Index STX OUTSP ; Update the Start Buffer Index LDA SNDBUF,X ; A:= Next Character RTS ; Return PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Input Buffer (28_Nov_84) ;----------------------------------------------------- ; ININS: TAX ;(save the character) LDY #0 ;Y_Index:= 0 LDA #$FF CMP (INEP),Y ;If (Buffer is NOT Full) BNE IISK2 TXA ; (restore character) STA (INEP),Y ; Put the Character in the Buffer INC INEP ; Increment the Storage Pointer BNE IISK1 INC INEP+1 LDA INEP+1 AND #7 ; (Last Location in Buffer is $7FF) ORA #HIGH INBUF ; (First Location in Buffer is $400) STA INEP+1 IISK1: RTS ; Return IISK2: STA BUFFULL ;Else Set the Buffer Full Flag RTS ; Return ;---------------------------------------------------------------------- ; Remove a Character from the Input Buffer (28_Nov_84) ;----------------------------------------------------- ; INREM: LDY #0 ;Y_Index:= 0 LDA (INSP),Y ;A:= Character from inbuf CMP #$FF ;If (There is a valid Character in the Buffer) BEQ IRSK2 TAX ; (save the character removed) LDA #$FF STA (INSP),Y ; mark the spot empty INC INSP BNE IRSK1 ; Adjust the Buffer Pointer INC INSP+1 LDA INSP+1 AND #7 ; (Last Location in Buffer is $7FF) ORA #HIGH INBUF ; (First Location in Buffer is $400) STA INSP+1 IRSK1: TXA ;(get char back) IRSK2: RTS ;Return PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Key Buffer (26_Nov_84) ;--------------------------------------------------- ; KEYINS: TAY ;Y:= Character to Store LDX KEYSP ;X:= Key Start Index TXA ;A:= Key Start Index CLC ADC #1 ;Increment the Start Pointer AND #$1F ;(Truncate Pointer to 32 Locations) CMP KEYEP ;If (Incremented Start Pointer ne End Pointer) BEQ KISK1 STA KEYSP ; Update the Key Start Pointer STY KEYBUF,X ; Put character in the Keyboard Buffer KISK1: RTS ;Return ;---------------------------------------------------------------------- ; Remove a Character from the Key Buffer (21_Nov_84) ;--------------------------------------------------- ; KEYREM: LDX KEYEP ;X:= Key End Index LDY KEYBUF,X ;Y:= Character from Keyboard Buffer INX TXA ;A:= Key End Index + 1 AND #$1F ;(Truncate Index to 32 Locations) STA KEYEP ;Update the Key End Pointer TYA ;A:= Character read from the Buffer RTS ;Return PAGE ;---------------------------------------------------------------------- ; Get a Character from the Keyboard ;---------------------------------- ; 1) returns with character in A reg ; GETKEY: LDX #0 STX PARTIAL ; clear input assembly area LDX #3 JSR KDLY ; wait 30 micro seconds LDY #8 ; set to receive 8 data bits from kbrd GTKLP1: LDA #1 ORA BDREG ; must not change other bits in baud register STA BAUD ; send request data to KBRD LDX #21 JSR KDLY ; wait 210 microseconds LDA BAUD AND #%10000000 ; get kbrd data bit ORA PARTIAL ; add in other bits STA PARTIAL ; save the bit(s) we have so far LDA BDREG STA BAUD ; clear request data DEY BEQ GTKSK1 ; if 0, then we have 8 bits, so go LDA PARTIAL ; else, set up partial for getting next bit added to it LSR A STA PARTIAL ; and restore partial LDX #10 JSR KDLY ; wait 100 micro secs JMP GTKLP1 ; then, go get the next bit GTKSK1: LDX #10 JSR KDLY LDA PARTIAL ; get the character we rcv'd RTS PAGE ;---------------------------------------------------------------------- ; Put a Character to the Keyboard (30_Nov_84) ;-------------------------------------------- ; 1) This routine sends the character in A reg to the keyboard. ; 2) If the last character sent was a bell then a delay is inserted ; before sending the character to give the keyboard time to transmit ; a character. ; PUTKEY: LDX BELSNT ;If (Last Character Sent was a Bell) BEQ PTKSK1 LDY #40 ; Y:= Number of 2560 us delays (.1 sec) PTKLP0: LDX #$FF ; Repeat X:= 2560 us Delay JSR KDLY ; Delay 2560 us DEY ; Decrement Delay Count BNE PTKLP0 ; Until (Number of 2560 us Delays eq 0) PTKSK1: LDX #0 ;Set Bell Flag to False (Zero) CMP #BEEP ;If (Current Character is a Bell) BNE PTKSK2 DEX ; Set Bell Flag to True (Non_Zero) PTKSK2: STX BELSNT ;Update the Bell Sent Flag SEI ;Disable Interrupts PHA ;(Save Char to Send) LDY #8 ;Y:= Bit Counter (set to send 8 data bits) PTKLP1: LDX BAUD ;While (Keyboard is trying to Send) BPL PTKSK3 PTKLP2: JSR FTCHKEY ; handle KBRD request as an interrupt JMP PTKLP1 PTKSK3: LDA #$1 ;assert attention to KBRD ORA BDREG ;but without affecting other bits STA BAUD LDX #1 ;Contention check JSR KDLY ;wait 10 micro seconds NOP NOP NOP ;(pad) LDX BAUD ;check if KBRD Ack asserted BPL ACK1 ;If ( keyboard Ack asserted) then LDA BDREG STA BAUD ; cancel request to keyboard, JMP PTKLP2 ; GoTo get the char from the keyboard ACK1: LDX BAUD ;Repeat wait for KBRD to request data BPL ACK1 PLA ; get char to send TAX ; save it LSR A ; shift it for next time through PHA ; put back on stack TXA ; get bit to send AND #1 ; only LSB is needed ORA BDREG ; be sure not to change rest of register STA BAUD ; output bit to KBRD PTKLP3: LDX BAUD ; wait for KBRD to ACK that it got bit BMI PTKLP3 DEY ; now, adjust number of bits left to send BNE ACK1 ;Until (all 8 bits sent) LDA BDREG ;go to quiescent state STA BAUD PLA ;restore stack CLI ;re-enable interrupts RTS ;Return END