;====================================================================== ; IRQ Handelers and I/O Routines (12_Nov_84) ;=========================================== ; ; 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 IRQRET ; if (keyboard locked) then return JSR KEYINS ; else, insert character key buffer IRQRET: PLA TAX ; restore registers PLA TAY PLA ; and return RTI PAGE ;---------------------------------------------------------------------- ; Non_Maskable Interrupt Entry Point ;----------------------------------- ; 1) Ok, we've got a character interrupt from the USART. ; NMIRET: LDA S1DATA ; clear NMI, and throw away the character PLA RTI NMIVEC: SEI ; disable interrupts PHA LDA NMIOK ; see if NMI is enabled CMP #$A5 ; must be A5 to handle interrupts BNE NMIRET TYA ; save other registers PHA TXA PHA LDA S1DATA ; GET A CHARACTER FROM USART AND #%01111111 ; ignore the eighth bit CMP #$0 ; don't put nulls in buffer BEQ NOINS JSR ININS ; put in incoming character buffer if room exists NOINS: PLA TAX PLA TAY PLA RTI PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Send Buffer ;---------------------------------------- ; SNDINS: TAY ; insert char in A into send buffer TXA ; save x register PHA LDA BRKHIT BEQ NOTHIT ; if (BRKHIT=TRUE) then CPY #CTRLC ; if ( char = ^C ) then BEQ SNDFULL ; return LDA #0 ; else STA BRKHIT ; BRKHIT <= FALSE ; put char in buffer if room exists NOTHIT: LDX OUTEP ; get end pointer of send buffer LDA SNDBUF,X ; see if buffer full CMP #$FF BNE SNDFULL ; if not FF, then buffer is full TYA STA SNDBUF,X ; else, put char into buffer INC OUTEP ; adjust ring pointer LDA #%01111111 AND OUTEP STA OUTEP SNDFULL:PLA ; restore x register TAX RTS PAGE ;---------------------------------------------------------------------- ; Remove a Character from the Send Buffer ;---------------------------------------- ; SNDREM: LDX OUTSP ; Remove a char from send buffer return it in A LDA SNDBUF,X ; get a char from sndbuf CMP #$FF BEQ NOCHAR ; if FF, then no char to remove TAY ; save the character removed LDA #$FF ; mark the spot empty STA SNDBUF,X INC OUTSP ; adjust ring pointer LDA #%01111111 AND OUTSP STA OUTSP TYA ; get char back RTS PAGE ;---------------------------------------------------------------------- ; Insert a Character into the Input Buffer ;----------------------------------------- ; ININS: TAX ; save the character LDY #0 LDA (INEP),Y ; get next character CMP #$FF BNE INFULL ; 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 INDONE LDA #2 INDONE: STA INEP+1 RTS INFULL: 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 NOCHAR ; 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 REMDONE LDA #2 REMDONE:STA INSP+1 TXA ; get char back NOCHAR: RTS ;---------------------------------------------------------------------- ; Insert a Character into the Key Buffer ;--------------------------------------- ; KEYINS: PHA ; save the character LDA KEYSP ; get pointer to start of keyboard buffer TAX CLC ; calculate next location ADC #1 AND #15 TAY CPY KEYEP ; see if at end ( BUFFER FULL ) BEQ KEYOVF ; yes, ignore key PLA ; get character back STY KEYSP ; update start of buffer STA KEYBUF,X ; Put char in keychar buffer RTS KEYOVF: PLA ; restore stack RTS PAGE ;---------------------------------------------------------------------- ; Remove a Character from the Key Buffer ;--------------------------------------- ; KEYREM: LDX KEYEP LDY KEYBUF,X INX TXA AND #15 STA KEYEP TYA RTS 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 NXTBIT: 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 GOTCHAR ; 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 NXTBIT ; then, go get the next bit GOTCHAR: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 RETRY: LDX BAUD ; check if KBRD trying to send BPL KBRDFRE ; jump if KBRD not trying to send a char ABORT: JSR FTCHKEY ; else, handle KBRD request as an interrupt JMP RETRY ; now, try again KBRDFRE: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 ABORT ; 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 ACK2: LDX BAUD ; wait for KBRD to ACK that it got bit BMI ACK2 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 PAGE END