OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [software/] [source/] [keyboard.asm] - Rev 53

Go to most recent revision | Compare with Previous | Blame | View Log


; ============================================================================
;        __
;   \\__/ o\    (C) 2015  Robert Finch, Stratford
;    \  __ /    All rights reserved.
;     \/_//     robfinch<remove>@finitron.ca
;       ||
;  
;
; 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/>.    
;                                                                          
;
; KeyState1_
; 76543210
;        + = keyup
;
; KeyState2_
; 76543210
; |||||||+ = shift
; ||||||+- = alt
; |||||+-- = control
; ||||+--- = numlock
; |||+---- = capslock
; ||+----- = scrolllock
; |+------ =
; +------- = extended
;
; ============================================================================
;
; Static Device Control Block for Keyboard
;
                align   8
                byte    8,"keyboard   "         ; DCB_Name      string: first byte is length, 11 chars max
                dh              0                                        ; DCB_Type                      0 = character
                dw              0                                        ; DCB_nBPB
                dw              0                                        ; DCB_LastErc           last error code
                dw              0                                        ; DCB_StartBlock        starting block number (partitioned devices)
                dw              0                                        ; DCB_nBlocks           number of blocks on device
                dw              KeybdCmdProc            ; DCB_pCmdProc          pointer to command processor routine
                byte    1                                       ; DCB_ReentCount        re-entrancy count (1 to 255)
                byte    0                                        ; DCB_fSingleUser
                fill.b  6,0
                dw              0                                        ; DCB_hJob                      handle to associated job
                dw              0                                        ; DCB_Mbx
                dw              0                                        ; DCB_pSema                     pointer to device semaphore
                dw              0                                        ; DCB_Resv1                     reserved
                dw              0                                        ; DCB_Resv2                     reserved

        align   8
kbd_jmp:
                jmp             KeybdIRQ[c0]

KeybdCmdProc:
                rts

KeybdInit:
                addui   sp,sp,#-8
                sws             c1,[sp]
                lla             r1,cs:kbd_jmp           ; set interrupt vector
                ldi             r2,#194
                bsr             set_vector
                lws             c1,[sp]
                addui   sp,sp,#8
KeybdClearBuf:
                lw              r29,zs:RunningJCB_
                sb              r0,zs:JCB_KeybdHead[r29]        ; clear buffer pointers
                sb              r0,zs:JCB_KeybdTail[r29]
                sb              r0,zs:JCB_KeyState1[r29]
                sb              r0,zs:JCB_KeyState2[r29]
                sb              r0,zs:JCB_KeybdLEDs[r29]
                ldi             r1,#64
                sb              r1,zs:JCB_KeybdBufSz[r29]
                rts

; Check if a key is available
; Returns:
;       r1 = non-zero if key is available, otherwise zero
;
public KeybdCheckForKey
                addui   sp,sp,#-8
                sw              r2,[sp]
                lw              r2,zs:RunningJCB_
                lcu             r1,zs:JCB_KeybdHead[r2]
                shrui   r2,r1,#8
                zxb             r1,r1
                eor             r1,r1,r2
                lw              r2,[sp]
                addui   sp,sp,#8
                rts
endpublic

public KeybdGetCharWait:
                ldi             r1,#-1
                lw              r29,zs:RunningJCB_
                sb              r1,zs:JCB_KeybdWaitFlag[r29]
                br              KeybdGetChar
endpublic

public KeybdGetCharNoWait:
                lw              r1,zs:RunningJCB_
                sb              r0,zs:JCB_KeybdWaitFlag[r1]
                br              KeybdGetChar
endpublic

; Wait for a keyboard character to be available
; Returns (-1) if no key available
; Return key >= 0 if key is available
;
;
KeybdGetChar:
KeybdGetChar1:
                addui   sp,sp,#-64
                sw              r2,[sp]
                sws             c1,8[sp]                ; save off link register
                sws             hs,16[sp]
                sws             hs.lmt,24[sp]
                sw              r3,32[sp]
                sws             ds,40[sp]
                sws             ds.lmt,48[sp]
                ldis    hs,#$FFD00000
                ldis    hs.lmt,#$100000
                lws             ds,zs:RunningJCB_
                ldis    ds.lmt,#$10000
.0002:
.0003:
                ; Allow for some interruptible code to occur
                nop nop nop     nop
                nop     nop     nop     nop
                nop     nop     nop     nop

                ; Get head and tail pointers as a single load
                ; then separate
;               sei
                sync
                lcu             r1,JCB_KeybdHead        ; 1 memory op instead of 2
                shrui   r2,r1,#8                ; r2 = tail index
                zxb             r1,r1                   ; r1 = head index
                cmp             p0,r1,r2                ; is there anything in the buffer ?
p0.ne   br              .0006                   ; yes, branch
                cli
                lb              r1,JCB_KeybdWaitFlag    ; are we waiting indefinitely for a key ?
                tst             p0,r1
p0.lt   br              .0003                   ; if yes, branch
                br              .0008                   ; otherwise exit no key available
.0006:
                ldi             r1,#$300
                sc              r1,hs:LEDS
                lbu             r1,JCB_KeybdBuf[r2]     ; get scan code from buffer
                lbu             r3,JCB_KeybdBufSz
                addui   r2,r2,#1                ; increment tail index
                cmp             p0,r2,r3
p0.geu  mov             r2,r0                   ; take modulus
                sb              r2,JCB_KeybdTail        ; and store it back
                cli
.0001:
                cmp             p0,r1,#SC_KEYUP ; keyup scan code ?
p0.eq   br              .doKeyup
                cmp             p0,r1,#SC_EXTEND; extended scan code ?
p0.eq   br              .doExtend
                cmp             p0,r1,#$14              ; control ?
p0.eq   br              .doCtrl
                cmp             p0,r1,#$12              ; left shift
p0.eq   br              .doShift
                cmp             p0,r1,#$59              ; right shift
p0.eq   br              .doShift
                cmp             p0,r1,#SC_NUMLOCK
p0.eq   br              .doNumLock
                cmp             p0,r1,#SC_CAPSLOCK
p0.eq   br              .doCapsLock
                cmp             p0,r1,#SC_SCROLLLOCK
p0.eq   br              .doScrollLock
                cmp             p0,r1,#SC_ALT
p0.eq   br              .doAlt
                lb              r2,JCB_KeyState1
                sb              r0,JCB_KeyState1
                biti    p0,r2,#1                ; was keyup set ?
p0.ne   br              .0003                   ; if yes, ignore and branch back
                lb              r2,JCB_KeyState2        ; Is extended code ?
                biti    p0,r2,#$80
p0.eq   br              .0010
                lb              r2,JCB_KeyState2        ; clear extended bit
                andi    r2,r2,#$7F
                sb              r2,JCB_KeyState2
                sb              r0,JCB_KeyState1        ; clear keyup
                andi    r1,r1,#$7F
                lbu             r1,cs:keybdExtendedCodes_[r1]
                br              .0008
.0010:
                biti    p0,r2,#4                ; Is Cntrl down ?
p0.eq   br              .0009
                andi    r1,r1,#$7F
                lbu             r1,cs:keybdControlCodes_[r1]
                br              .0008
.0009:
                biti    p0,r2,#33               ; Is shift or CAPS-Lock down ?
p0.ne   lbu             r1,cs:shiftedScanCodes_[r1]
p0.eq   lbu             r1,cs:unshiftedScanCodes_[r1]
.0008:
                lw              r2,[sp]
                lws             c1,8[sp]
                lws             hs,16[sp]
                lws             hs.lmt,24[sp]
                lw              r3,32[sp]
                lws             ds,40[sp]
                lws             ds.lmt,48[sp]
                addui   sp,sp,#64
                rts

.doKeyup:
                lb              r2,JCB_KeyState1        ; set keyup flag
                ori             r2,r2,#1
                sb              r2,JCB_KeyState1
                br              .0003
.doExtend:
                lb              r2,JCB_KeyState2
                ori             r2,r2,#$80
                sb              r2,JCB_KeyState2
                br              .0003
.doCtrl:
                lb              r2,JCB_KeyState1
                biti    p0,r2,#1
                lbu             r2,JCB_KeyState2
p0.eq   ori             r2,r2,#4
p0.ne   andi    r2,r2,#~4
                sb              r2,JCB_KeyState2
                br              .0003
.doAlt:
                lb              r2,JCB_KeyState1
                biti    p0,r2,#1
                lbu             r2,JCB_KeyState2
p0.eq   ori             r2,r2,#2
p0.ne   andi    r2,r2,#~2
                sb              r2,JCB_KeyState2
                br              .0003
.doShift:
                lb              r2,JCB_KeyState1
                biti    p0,r2,#1
                lbu             r2,JCB_KeyState2
p0.eq   ori             r2,r2,#1
p0.ne   andi    r2,r2,#~1
                sb              r2,JCB_KeyState2
                br              .0003
.doNumLock:
                lbu             r2,JCB_KeyState2
                eori    r2,r2,#16
                sb              r2,JCB_KeyState2
                bsr             KeybdSetLEDStatus
                br              .0003
.doCapsLock:
                lbu             r2,JCB_KeyState2
                eori    r2,r2,#32
                sb              r2,JCB_KeyState2
                bsr             KeybdSetLEDStatus
                br              .0003
.doScrollLock:
                lbu             r2,JCB_KeyState2
                eori    r2,r2,#64
                sb              r2,JCB_KeyState2
                bsr             KeybdSetLEDStatus
                br              .0003

;------------------------------------------------------------------------------
; Set the keyboard LED status leds.
; Trashes r1, p0
;------------------------------------------------------------------------------

KeybdSetLEDStatus:
                addui   r27,r27,#-8
                sws             c1,[r27]
                sb              r0,KeybdLEDs
                lb              r1,JCB_KeyState2
                biti    p0,r1,#16
p0.ne   lb              r1,KeybdLEDs    ; set bit 1 for Num lock, 0 for scrolllock , 2 for caps lock
p0.ne   ori             r1,r1,#2
p0.ne   sb              r1,KeybdLEDs
                lb              r1,JCB_KeyState2
                biti    p0,r1,#32
p0.ne   lb              r1,KeybdLEDs
p0.ne   ori             r1,r1,#4
p0.ne   sb              r1,KeybdLEDs
                lb              r1,JCB_KeyState2
                biti    p0,r1,#64
p0.ne   lb              r1,KeybdLEDs
p0.ne   ori             r1,r1,#1
p0.ne   sb              r1,KeybdLEDs
                ldi             r1,#$ED
                sb              r1,hs:KEYBD             ; set status LEDs command
                bsr             KeybdWaitTx
                bsr             KeybdRecvByte
                cmpi    p0,r1,#$FA
                lb              r1,KeybdLEDs
                sb              r1,hs:KEYBD             
                bsr             KeybdWaitTx
                bsr             KeybdRecvByte
                lws             c1,[r27]
                addui   r27,r27,#8
                rts

;------------------------------------------------------------------------------
; Receive a byte from the keyboard, used after a command is sent to the
; keyboard in order to wait for a response.
;
; Returns:
;       r1 >= 0 if a scancode is available
;   r1 = -1 on timeout
;------------------------------------------------------------------------------
;
KeybdRecvByte:
                addui   r27,r27,#-16
                sws             c1,8[r27]
                sw              r3,[r27]
                ldi             r3,#20                  ; wait up to .2s
.0003:
                bsr             KeybdWaitBusy
                lb              r1,hs:KEYBD+1   ; wait for response from keyboard
                biti    p0,r1,#$80              ; is input buffer full ?
p0.ne   br              .0004                   ; yes, branch
                bsr             Wait10ms                ; wait a bit
                addui   r3,r3,#-1
                tst             p0,r3
p0.ne   br              .0003                   ; go back and try again
                lw              r3,[r27]                ; timeout
                lws             c1,8[r27]
                addui   r27,r27,#16
                ldi             r1,#-1
                rts
.0004:
                lvb             r1,hs:KEYBD             ; get scancode
                zxb             r1,r1                   ; convert to unsigned char
                sb              r0,hs:KEYBD+1   ; clear recieve state
                lw              r3,[r27]
                lws             c1,8[r27]
                addui   r27,r27,#16
                rts                                             ; return char in r1

;------------------------------------------------------------------------------
; Wait until the keyboard isn't busy anymore
; Wait until the keyboard transmit is complete
; Returns:
;    r1 >= 0 if successful
;        r1 < 0 if timed out
;------------------------------------------------------------------------------
;
KeybdWaitBusy:                          ; alias for KeybdWaitTx
KeybdWaitTx:
                addui   r27,r27,#-16
                sws             c1,8[r27]
                sw              r3,[r27]
                ldi             r3,#10                  ; wait a max of .1s
.0001:
                lvb             r1,hs:KEYBD+1
                biti    p0,r1,#$40              ; check for transmit busy bit
p0.eq   br              .0002                   ; branch if bit clear
                bsr             Wait10ms                ; delay a little bit
                addui   r3,r3,#-1               ; go back and try again
                tst             p0,r3
p0.ne   br              .0001
                lw              r3,[r27]                ; timed out
                lws             c1,8[r27]
                addui   r27,r27,#16
                ldi             r1,#-1                  ; return -1
                rts
.0002:
                lw              r3,[r27]                ; wait complete, return 
                lws             c1,8[r27]               ; restore return address
                ldi             r1,#0                   ; return 0 for okay
                addui   r27,r27,#16
                rts

;------------------------------------------------------------------------------
; Delay for about 10 ms.
;------------------------------------------------------------------------------

Wait10ms:
                addui   r27,r27,#-16
                sw              r1,8[r27]
                sw              r2,[r27]
                mfspr   r1,tick
                addui   r1,r1,#250000   ; 10ms at 25 MHz
.0001:
                mfspr   r2,tick
                cmp             p0,r2,r1
p0.lt   br              .0001
                lw              r2,[r27]
                lw              r1,8[r27]
                addui   r27,r27,#16
                rts

;------------------------------------------------------------------------------
; KeybdIRQ:
;     Store scancode in keyboard buffer. Also check for the special key
; sequences ALT-tab and CTRL-ALT-del. If the keyboard buffer is full then
; the newest keystrokes are lost. 
;------------------------------------------------------------------------------

KeybdIRQ:
                sync
                addui   r31,r31,#-80
                sws             p0,[r31]
                sw              r1,8[r31]
                sw              r2,16[r31]
                sws             hs,24[r32]
                sw              r3,32[r31]
                sws             ds,40[r31]
                sws             ds.lmt,48[r31]
                sws             hs.lmt,56[r31]
                sw              r4,64[r31]
                sw              r5,72[r31]

                ldis    hs,#$FFD00000
                ldis    hs.lmt,#$100000
                lws             ds,zs:IOFocusNdx_       ; set input to correct keyboard buffer
                ldis    ds.lmt,#$10000
                lvb             r1,hs:KEYBD                     ; get the scan code
                sb              r0,hs:KEYBD+1           ; clear interrupt status
                lcu             r2,JCB_KeybdHead        ; get head/tail index (1 memory op)
                shrui   r3,r2,#8                        ; r3 = tail
                zxb             r2,r2                           ; r2 = head
                mov             r4,r2                           ; make copy of old head index
                addui   r2,r2,#1                        ; increment head index
                lbu             r5,JCB_KeybdBufSz
                cmp             p0,r2,r5
p0.geu  mov             r2,r0                           ; modulus buffer size
                cmp             p0,r2,r3                        ; is there room in buffer ?
p0.ne   sb              r1,JCB_KeybdBuf[r4]     ; store scan code in buffer
p0.ne   sb              r2,JCB_KeybdHead        ; save buffer index
                lb              r2,JCB_KeyState2        ; check for ALT
                biti    p0,r2,#2
p0.eq   br              .exit
                cmpi    p0,r1,#SC_TAB
p0.eq   inc.b   zs:iof_switch_          ; set IOF switch flag if ALT-Tab pressed.
p0.eq   br              .exit
                cmpi    p0,r1,#SC_DEL
p0.ne   br              .exit
                biti    p0,r2,#4                        ; check for CTRL-ALT-DEL
p0.ne   jmp             cold_start
.exit:
                lws             p0,[r31]
                lw              r1,8[r31]
                lw              r2,16[r31]
                lws             hs,24[r32]
                lw              r3,32[r31]
                lws             ds,40[r31]
                lws             ds.lmt,48[r31]
                lws             hs.lmt,56[r31]
                lw              r4,64[r31]
                lw              r5,72[r31]
                addui   r31,r31,#80
                sync
                rti

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.