SBTTL 'IRQ Handelers and I/O Routines (26_Nov_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 ; KBRDOUT 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 ; FTCHKEY:PLA ; fix so RTI returns properly TAX INX TXA PHA PHP IRQVEC: PHA TYA ; else PHA ; save registers TXA PHA JSR GETKEY ; get key from keyboard LDY LOCKMD ; see if keyboard locked BMI IRQSK1 ; if (keyboard locked) then return JSR KEYINS ; else, insert character key buffer IRQSK1: PLA TAX ; restore registers PLA TAY PLA ; and return RTI PAGE ;---------------------------------------------------------------------- ; Non_Maskable Interrupt Entry Point (26_Nov_84) ;----------------------------------------------- ; 1) Ok, we've got a character interrupt from the USART. ; NMIVEC: SEI ;disable interrupts PHA LDA NMIOK ;see if NMI is enabled CMP #$A5 ;(must be A5 to handle interrupts) BNE NMISK2 ;If (Interrupts are Enabled) TYA ; Save other registers PHA TXA PHA LDA S1DATA ; Get a Character from the Usart AND #%01111111 ; (remove the parity bit) BEQ NMISK1 ; If (Char ne 0) JSR ININS ; Insert it into the Input Buffer NMISK1: PLA ; Restore Registers TAX PLA TAY PLA RTI ; Return NMISK2: LDA S1DATA ;Else clear NMI, and throw away the character PLA RTI ; Return PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Send Buffer ;---------------------------------------- ; SNDINS: TAY ;Y:= Character to Store TXA ;Save the X Register PHA LDA BRKHIT ;If (BrkHit eq True) BEQ SISK1 CPY #CTRLC ; If (Character to Store eq ^C) BEQ SISK2 ; return LDA #0 ; Else STA BRKHIT ; BRKHIT = FALSE SISK1: LDX OUTEP ;X:= end pointer of send buffer LDA SNDBUF,X ;If (Buffer ne Full) CMP #$FF BNE SISK2 TYA ; A:= Character to Store STA SNDBUF,X ; Store the Character INC OUTEP LDA #%01111111 ; (Truncate the Pointer to le 127) AND OUTEP STA OUTEP ; Update the Send Buffer End Pointer SISK2: PLA ;restore x register TAX RTS ;Return ;---------------------------------------------------------------------- ; Remove a Character from the Send Buffer ;---------------------------------------- ; SNDREM: LDX OUTSP ;X:= Index into the Send Buffer LDA SNDBUF,X ;A:= Next Character CMP #$FF BEQ SRSK1 ;If (Character ne 0FFh) TAY ; save character in the Y index LDA #$FF ; mark the spot empty STA SNDBUF,X INC OUTSP LDA #%01111111 ; (truncate the buffer pointer) AND OUTSP STA OUTSP ; Update the Removal Pointer TYA ; restore character to the Accm SRSK1: RTS ;Return PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Input Buffer ;----------------------------------------- ; ININS: TAX ; save the character LDY #0 LDA (INEP),Y ; get next character CMP #$FF BNE IISK2 ; if not FF, then the buffer is full TXA ; else, put the char into buffer STA (INEP),Y CLC ; adjust end of pointer LDA #1 ADC INEP STA INEP LDA #0 ADC INEP+1 CMP #4 BNE IISK1 LDA #2 IISK1: STA INEP+1 RTS IISK2: LDA #$FF STA BUFFULL RTS PAGE ;---------------------------------------------------------------------- ; Remove a Character from the Input Buffer ;----------------------------------------- ; INREM: LDY #0 ; Remove a char from input buffer return it in A LDA (INSP),Y ; get a char from inbuf CMP #$FF BEQ IRSK2 ; if FF, then no char to remove TAX ; save the character removed LDA #$FF ; mark the spot empty STA (INSP),Y CLC ; adjust ring pointer LDA #1 ADC INSP STA INSP LDA #0 ADC INSP+1 CMP #4 BNE IRSK1 LDA #2 IRSK1: STA INSP+1 TXA ; get char back IRSK2: RTS 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 ;-------------------------------- ; 1) sends the character in A reg to the kbrd ; KBRDOUT:SEI ; disable interrupts PHA ; save char to send LDY #8 ; set to send 8 data bits KBOLP1: LDX BAUD ; check if KBRD trying to send BPL KBOSK1 ; jump if KBRD not trying to send a char KBOLP2: JSR FTCHKEY ; else, handle KBRD request as an interrupt JMP KBOLP1 ; now, try again KBOSK1: 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 KBOLP2 ; and go get the char from the keyboard ACK1: LDX BAUD ; 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 KBOLP3: LDX BAUD ; wait for KBRD to ACK that it got bit BMI KBOLP3 DEY ; now, adjust number of bits left to send BNE ACK1 ; if 8 bits not sent, then start again LDA BDREG ; else, go to quiescent state STA BAUD PLA ; restore stack CLI ; re-enable interrupts RTS END