URL
https://opencores.org/ocsvn/rf6809/rf6809/trunk
Subversion Repositories rf6809
[/] [rf6809/] [trunk/] [software/] [boot/] [keyboard.asm] - Rev 17
Go to most recent revision | Compare with Previous | Blame | View Log
; ============================================================================; __; \\__/ o\ (C) 2013-2022 Robert Finch, Waterloo; \ __ / All rights reserved.; \/_// robfinch<remove>@opencores.org; ||;;; Keyboard driver routines to interface to a PS2 style keyboard; Converts the scancode to ascii;; This source file is free software: you can redistribute it and/or modify; it under the terms of the GNU Lesser General Public License as published; by the Free Software Foundation, either version 3 of the License, or; (at your option) any later version.;; This source file is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program. If not, see <http://www.gnu.org/licenses/>.;; ============================================================================;SC_F12 EQU $07SC_C EQU $21SC_T EQU $2CSC_Z EQU $1ASC_DEL EQU $71 ; extendSC_KEYUP EQU $F0 ; should be $f0SC_EXTEND EQU $E0SC_CTRL EQU $14SC_RSHIFT EQU $59SC_NUMLOCK EQU $77SC_SCROLLLOCK EQU $7ESC_CAPSLOCK EQU $58SC_ALT EQU $11;#define SC_LSHIFT EQU $12;SC_DEL EQU $71 ; extend;SC_LCTRL EQU $58SC_TAB EQU $0D; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Recieve a byte from the keyboard, used after a command is sent to the; keyboard in order to wait for a response.;; Parameters: none; Returns: accd = recieved byte ($00 to $FF), -1 on timeout; Modifies: acc; Stack Space: 2 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdRecvByte:pshs xldx #100 ; wait up to 1skrb3:bsr KeybdGetStatus ; wait for response from keyboardtstbbmi krb4 ; is input buffer full ? yes, branchbsr Wait10ms ; wait a bitdexbne krb3 ; go back and try againldd #-1 ; return -1puls x,pckrb4:bsr KeybdGetScancodepuls x,pc; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Send a byte to the keyboard.;; Parameters: accb byte to send; Returns: none; Modifies: none; Stack Space: 0 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdSendByte:stb KEYBDrts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Wait until the keyboard transmit is complete;; Parameters: none; Returns: r1 = 0 if successful, r1 = -1 timeout; Modifies: r1; Stack Space: 3 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdWaitTx:pshs xldx #100 ; wait a max of 1skwt1:bsr KeybdGetStatusandb #$40 ; check for transmit complete bit; branch if bit setbne kwt2bsr Wait10ms ; delay a little bitdexbne kwt1 ; go back and try againldd #-1 ; timed out, return -1puls x,pckwt2:clra ; wait complete, return 0clrbpuls x,pc; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Wait for 10 ms;; Parameters: none; Returns: none; Modifies: none; Stack Space: 2 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Wait10ms:pshs dlda MSCOUNT+3W10_0001:tfr a,bsubb MSCOUNT+3cmpb #$FFAbhi W10_0001puls d,pc; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Wait for 300 ms (256 ms);; Parameters: none; Returns: none; Modifies: none; Stack Space: 2 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Wait300ms:pshs dlda MSCOUNT+3W300_0001:tfr a,bsubb MSCOUNT+3cmpb #$F00bhi W300_0001puls d,pc; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Get the keyboard status;; Parameters: none; Returns: d = status; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdGetStatus:kbgs3:ldb KEYBD+1bitb #$80bne kbgs1bitb #$01 ; check parity error flagbne kbgs2clrartskbgs2:ldb #$FE ; request resendbsr KeybdSendBytebsr KeybdWaitTxbra kbgs3kbgs1: ; return negative statusorb #$F00lda #-1rts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Get the scancode from the keyboard port;; Parameters: none; Returns: acca = scancode; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdGetScancode:clraldb KEYBD ; get the scan codeclr KEYBD+1 ; clear receive register (write $00 to status reg)rts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Set the LEDs on the keyboard.;; Parameters: d LED status to set; Returns: none; Modifies: none; Stack Space: 2 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdSetLED:pshs bldb #$ED ; set LEDs commandbsr KeybdSendBytebsr KeybdWaitTxbsr KeybdRecvByte ; should be an ackpuls bbsr KeybdSendBytebsr KeybdWaitTxbsr KeybdRecvByte ; should be an ackrts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Get ID - get the keyboards identifier code.;; Parameters: none; Returns: d = $AB83, $00 on fail; Modifies: d, KeybdID updated; Stack Space: 2 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdGetID:ldb #$F2bsr KeybdSendBytebsr KeybdWaitTxbsr KeybdRecvBytebitb #$80bne kgnotKbdcmpb #$ABbne kgnotKbdbsr KeybdRecvBytebitb #$80bne kgnotKbdcmpb #$83bne kgnotKbdldd #$AB83kgid1:std KeybdIDrtskgnotKbd:clraclrbbra kgid1; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Initialize the keyboard.;; Parameters:; none; Modifies:; none; Returns:; none; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdInit:pshs d,yldy #5clr KeyState1 ; records key up/down stateclr KeyState2 ; records shift,ctrl,alt statekbdi0002:bsr Wait10msclr KEYBD+1 ; clear receive register (write $00 to status reg)ldb #-1 ; send reset code to keyboardstb KEYBD+1 ; write $FF to status reg to clear TX statebsr KeybdSendByte ; now write to transmit registerbsr KeybdWaitTx ; wait until no longer busybsr KeybdRecvByte ; look for an ACK ($FA)cmpb #$FAbne kbdiTryAgainbsr KeybdRecvByte ; look for BAT completion code ($AA)cmpb #$FC ; reset error ?beq kbdiTryAgaincmpb #$AA ; reset complete okay ?bne kbdiTryAgain; After a reset, scan code set #2 should be active.config:ldb #$F0 ; send scan code selectstb LEDSbsr KeybdSendBytebsr KeybdWaitTxtstbbmi kbdiTryAgainbsr KeybdRecvByte ; wait for response from keyboardtstabmi kbdiTryAgaincmpb #$FA ; ACKbeq kbdi0004kbdiTryAgain:deybne kbdi0002.keybdErr:ldd #msgBadKeybdlbsr DisplayStringCRLFbra ledxitkbdi0004:ldb #2 ; select scan code set #2bsr KeybdSendBytebsr KeybdWaitTxtstbbmi kbdiTryAgainbsr KeybdRecvByte ; wait for response from keyboardtstabmi kbdiTryAgaincmpb #$FAbne kbdiTryAgainbsr KeybdGetIDledxit:ldb #$07bsr KeybdSetLEDbsr Wait300msldb #$00bsr KeybdSetLEDpuls d,y,pcmsgBadKeybd:fcb "Keyboard error",0;------------------------------------------------------------------------------; Calculate number of character in input buffer;; Parameters:; y = $Cn00000 where n is core id; Returns:; d = number of bytes in buffer.;------------------------------------------------------------------------------kbdRcvCount:clraldb kbdTailRcv,ysubb kbdHeadRcv,ybge krcXitldb #$40subb kbdHeadRcv,yaddb kbdTailRcv,ykrcXit:rts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdIRQ:lda KEYBD+1 ; check statusbita #$80 ; was key pressed?beq notKbdIRQ ; if not, exitldb KEYBD ; get the scan codeclr KEYBD+1 ; clear receive register (write $00 to status reg)pshs b ; save it offlda IOFocusID ; compute core memory address $Cn0000clrbaslaaslaaslaaslaora #$C00 ; address $Cn0000tfr d,y ; y =bsr kbdRcvCount ; get count of scan codes in buffercmpb #64 ; check if buffer full?bhs kbdBufFull ; if buffer full, ignore new keystroketfr y,x ; compute fifo addressldb kbdTailRcv,y ; b = buffer indexpuls a ; get back scancodeleax kbdFifo,x ; x = base address for fifosta b,x ; store in bufferincb ; increment buffer indexandb #$3f ; wrap around at 64 charsstb kbdTailRcv,y ; update itlda #28 ; Keyboard is IRQ #28sta IrqSource ; stuff a byte indicating the IRQ source for PEEK()notKbdIRQ:rtskbdBufFull:leas 1,s ; get rid of saved scancoderts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DBGCheckForKey:bra KeybdGetStatus; KeyState2 variable bit meanings;1176543210; ||||||||+ = shift; |||||||+- = alt; ||||||+-- = control; |||||+--- = numlock; ||||+---- = capslock; |||+----- = scrolllock; ||+------ = <empty>; |+------- = "; | = "; | = "; | = "; +-------- = extended; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Keyboard get routine.;; The routine may get characters directly from the scancode input or less; directly from the scancode buffer, if things are interrupt driven.;; Parameters:; b: bit 11 = blocking status 1=blocking, 0=non blocking; b: bit 1 = scancode source 1=scancode buffer, 0=direct; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -GetKey:pshs x,ystb KeybdBlock ; save off blocking statusdbgk2:ldb KeybdBlockpshs bbitb #1 ; what is the scancode sourcebeq dbgk20 ; branch if direct readlda COREID ; compute core memory addressclrbaslaaslaaslaaslaora #$C00tfr d,y ; y = $Cn0000bsr kbdRcvCounttstb ; anything in buffer?puls bbne dbgk1 ; branch if something in buffertstbbmi dbgk2 ; if no key and blocking - loopbra dbgk24dbgk20:ldy #0bsr KeybdGetStatusandb #$80 ; is key available?puls bbne dbgk1 ; branch if keytstb ; block?bmi dbgk2 ; If no key and blocking - loopdbgk24:ldd #-1 ; return -1 if no block and no keypuls x,y,pcdbgk1:cmpy #0bne dbgk22bsr KeybdGetScancode ; get scancode directlybra dbgk23dbgk22:; Retrieve value from scancode buffertfr y,xleax kbdFifo,x ; x = fifo addressldb kbdHeadRcv,y ; b = buffer indexlda b,x ; get the scancodeincb ; increment fifo indexandb #$3f ; and wrap aroundstb kbdHeadRcv,y ; save it backtfr a,b ; the scancode is needed in accbdbgk23:; lbsr DispByteAsHex; Make sure there is a small delay between scancode readsldx #20dbgk3:dexbne dbgk3; switch on scan codecmpb #SC_KEYUPbne dbgk4stb KeyState1 ; make KeyState1 <> 0bra dbgk2 ; loop backdbgk4:cmpb #SC_EXTENDbne dbgk5lda KeyState2ora #$800sta KeyState2bra dbgk2dbgk5:cmpb #SC_CTRLbne dbgkNotCtrltst KeyState1bne dbgk7lda KeyState2ora #4sta KeyState2bra dbgk8dbgk7:lda KeyState2anda #~4sta KeyState2dbgk8:clr KeyState1bra dbgk2dbgkNotCtrl:cmpb #SC_RSHIFTbne dbgkNotRshifttst KeyState1bne dbgk9lda KeyState2ora #1sta KeyState2bra dbgk10dbgk9:lda KeyState2anda #~1sta KeyState2dbgk10:clr KeyState1bra dbgk2dbgkNotRshift:cmpb #SC_NUMLOCKbne dbgkNotNumlocklda KeyState2eora #16sta KeyState2lda KeyLEDeora #2sta KeyLEDtfr a,bclrabsr KeybdSetLEDbra dbgk2dbgkNotNumlock:cmpb #SC_CAPSLOCKbne dbgkNotCapslocklda KeyState2eora #32sta KeyState2lda KeyLEDeora #4sta KeyLEDtfr a,bclrabsr KeybdSetLEDbra dbgk2dbgkNotCapslock:cmpb #SC_SCROLLLOCKbne dbgkNotScrolllocklda KeyState2eora #64sta KeyState2lda KeyLEDeora #1sta KeyLEDtfr a,bclrabsr KeybdSetLEDbra dbgk2dbgkNotScrolllock:cmpb #SC_ALTbne dbgkNotAlttst KeyState1bne dbgk11lda KeyState2ora #2sta KeyState2bra dbgk12dbgk11:lda KeyState2anda #~2sta KeyState2dbgk12:clr KeyState1bra dbgk2dbgkNotAlt:tst KeyState1beq dbgk13clr KeyState1bra dbgk2dbgk13:lda KeyState2 ; Check for CTRL-ALT-DELanda #6cmpa #6bne dbgk14cmpb #SC_DELbne dbgk14jmp [$FFFFFC] ; jump to NMI vectordbgk14:tst KeyState2 ; extended code?bpl dbgk15lda KeyState2anda #$7FFsta KeyState2ldx #keybdExtendedCodesbra dbgk18dbgk15:lda KeyState2 ; Is CTRL down?bita #4beq dbgk16ldx #keybdControlCodesbra dbgk18dbgk16:bita #1 ; Is shift down?beq dbgk17ldx #shiftedScanCodesbra dbgk18dbgk17:ldx #unshiftedScanCodesdbgk18:ldb b,x ; load accb with ascii from tableclrapuls x,y,pc ; and return
Go to most recent revision | Compare with Previous | Blame | View Log
