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

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [software/] [asm/] [keyboard.asm] - Rev 40

Compare with Previous | Blame | View Log


; ============================================================================
;        __
;   \\__/ o\    (C) 2013, 2014  Robert Finch, Stratford
;    \  __ /    All rights reserved.
;     \/_//     robfinch<remove>@opencores.org
;       ||
;  
;
; 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/>.    
;
; keyboard.asm                                                                         
; ============================================================================
;
DCMD_INITIALIZE         EQU             0
DCMD_MEDIA_CHK          EQU             1
DCMD_BUILD_BPB          EQU             2
DCMD_IOCTRL_READ        EQU             3
DCMD_READ                       EQU             4
DCMD_PEEK                       EQU             5
DCMD_INPUT_STATUS       EQU             6
DCMD_FLUSH_INPUT        EQU             7
DCMD_WRITE                      EQU             8
DCMD_WRITE_VERIFY       EQU             9
DCMD_OUTPUT_STATUS      EQU             10
DCMD_FLUSH_OUTPUT       EQU             11
DCMD_IOCTRL_WRITE       EQU             12
DCMD_OPEN                       EQU             13
DCMD_CLOSE                      EQU             14
DCMD_IS_REMOVEABLE      EQU             15
DCMD_OUTPUT_UNTIL_BUSY  EQU     16
DCMD_IRQ                        EQU             0xFFFFFFFD
DCMD_GETCHAR            EQU             32

DRSP_DONE                       EQU             1

                cpu             RTF65002

                .code
;------------------------------------------------------------------------------
;       The keyboard interrupt is selectively disabled and enabled to protect
; the keyboard buffers structure. Other interrupts are still enabled.
;------------------------------------------------------------------------------

macro DisKeybd
        pha
        lda             #15
        sta             PIC+2
        pla
endm

macro EnKeybd
        pha
        lda             #15
        sta             PIC+3
        pla
endm

        align   4
        ; Device driver struct
        dw              0xFFFFFFFF                      ; link to next device
        dw              0x00008001                      ; device attributes
        dw              KeybdStrategy           ; strategy routine
        dw              KeybdIRQ                        ; interrupt routine
        dw              KeybdCmdProc            ; command processor

        align   4
        dw      KeybdNop
        dw      KeybdInit
        dw      KeybdMediaChk
        dw      KeybdBuildBPB
        dw      KeybdGetChar                    ; GetChar()
        dw      KeybdCheckForKey                ; PeekChar()
        dw      KeybdGetCharDirect              ; unbuffered GetChar()
        dw      KeybdCheckForKeyDirect  ; unbuffered PeekChar()
        dw      SendByteToKeybd                 ; KeybdPutChar
        dw      SetKeyboardEcho
        dw      KeybdSetpos                             ; set position

;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
public KeybdDCB:
        align   4
        db      "KBD1        "  ; name
        dw      4       ; number of chars in name
        dw      1       ; type
        dw      1       ; nBPB
        dw      0        ; last erc
        dw      0        ; nBlocks
        dw      KeybdCmdProc
        dw      KeybdInit
        dw      KeybdStat
        dw      1       ; reentrancy count (1 to 255 are valid)
        dw      0        ; single user
        dw      0        ; hJob
        dw      0        ; OSD1
        dw      0        ; OSD2
        dw      0        ; OSD3
        dw      0        ; OSD4
        dw      0        ; OSD5
        dw      0        ; OSD6

KeybdStrategy:
        rts
KeybdCmdProc:
        rts
KeybdStat:
        rts
KeybdBuildBPB:
        rts
KeybdSetpos:
        rts
KeybdNop:
        lda             #E_Ok
        rts

;------------------------------------------------------------------------------
; Setup keyboard
;
; Issues a 'reset keyboard' command to the keyboard, then selects scan code
; set #2 (the most common one). Also sets up the keyboard buffer and
; initializes the keyboard semaphore.
;------------------------------------------------------------------------------
;
message "KeybdSetup"
public KeybdSetup:
        lda             #1                      ; setup semaphore
        sta             keybd_sema
        lda             #32
        sta             LEDS
        ldx             #0

        ; Set Keyboard IRQ vector       
        tsr             vbr,r2
        and             r2,#-2
        lda             #KeybdIRQ
        sta             448+15,x

        lda             #15                             ; enable kbd_irq
        sta             PIC+3

        jsr             KeybdInit

        lda             #1                              ; keyboard is device #1
        ldx             #KeybdDCB               ; pointer to DCB
        ldy             #1                              ; number of DCB's to setup
        ld              r4,#1                   ; Flag: is okay to replace existing device
;       jsr             InitDevDrv
        stz             keybdInIRQ
        inc             keybdIsSetup    ; set the setup flag
        rts

KeybdInit:
        lda             #33
        sta             LEDS
        lda             #$ff            ; issue keyboard reset
        jsr             SendByteToKeybd
        lda             #38
        sta             LEDS
        lda             #4
;       jsr             Sleep
        lda             #1000000                ; delay a bit
kbdi5:
        dea
        sta             LEDS
        bne             kbdi5
        lda             #34
        sta             LEDS
        lda             #0xf0           ; send scan code select
        jsr             SendByteToKeybd
        lda             #35
        sta             LEDS
        ldx             #0xFA
        jsr             WaitForKeybdAck
        cmp             #$FA
        bne             kbdi2
        lda             #36
        sta             LEDS
        lda             #2                      ; select scan code set#2
        jsr             SendByteToKeybd
        lda             #39
        sta             LEDS
kbdi2:
        rts
        
msgBadKeybd:
        db              "Keyboard not responding.",0

SendByteToKeybd:
        phx
        ldx             IOFocusNdx
        sta             KEYBD
        lda             #40
        sta             LEDS
        tsr             TICK,r3
kbdi4:                                          ; wait for transmit complete
        tsr             TICK,r4
        sub             r4,r4,r3
        cmp             r4,#1000000
        bhi             kbdbad
        lda             #41
        sta             LEDS
        lda             KEYBD+3
        bit             #64
        beq             kbdi4
        bra             sbtk1
kbdbad:
        lda             #42
        sta             LEDS
        lda             JCB_KeybdBad,x
        bne             sbtk2
        lda             #1
        sta             JCB_KeybdBad,x
        lda             #43
        sta             LEDS
        lda             #msgBadKeybd
        jsr             DisplayStringCRLFB
sbtk1:
        lda             #44
        sta             LEDS
        plx
        rts
sbtk2:
        bra             sbtk1
        
; Wait for keyboard to respond with an ACK (FA)
;
WaitForKeybdAck:
        lda             #64
        sta             LEDS
        tsr             TICK,r3
wkbdack1:
        tsr             TICK,r4
        sub             r4,r4,r3
        cmp             r4,#1000000
        bhi             wkbdbad
        lda             #65
        sta             LEDS
        lda             KEYBD
        bit             #$8000
        beq             wkbdack1
;       lda             KEYBD+8
        and             #$ff
wkbdbad:
        rts

; Wait for keyboard to respond with an ACK (FA)
; This routine picks up the ack status left by the
; keyboard IRQ routine.
; r2 = 0xFA (could also be 0xEE for echo command)
;
WaitForKeybdAck2:
        phy
        ldy             IOFocusNdx
WaitForKeybdAck2a:
        lda             JCB_KeybdAck,y
        cmp             r1,r2
        bne             WaitForKeybdAck2a
        stz             JCB_KeybdAck,y
        ply
        rts

;------------------------------------------------------------------------------
; Code in the works.
;------------------------------------------------------------------------------
;
comment ~
public KeybdService:
        lda             #keybd_mbx
        jsr             AllocMbx
        jsr             KeybdSetup
kbds3:
        ; Wait for a message to arrive at the service
        lda             keybd_mbx
        ldx             #-1                             ; wait forever
        jsr             WaitMsg
        cpx             #DCMD_IRQ
        beq             kbds1
        cpx             #DCMD_GETCHAR
        beq             kbds2
        cpx             #DCMD_INITIALIZE
        beq             kbds4
        bra             kbds3
kbds1:
        tyx             ; D2 holds character
        jsr             IKeybdIRQ
        bra             kbds3
kbds2:
        ; The mailbox number is the same as the TCB number
        tya
        jsr             IKeybdGetChar
        ; Send a message back to the requester containing the key value.
        tax
        tya
        ldy             #0
        jsr             SendMsg 
        bra             kbds3           
kbds4:
        jsr             KeybdInit
        bra             kbds3
~
comment ~
public XKeybdIRQ:
        pha
        phx
        phy
        lda             keybd_mbx
        ldx             #DCMD_IRQ
        ldy             KEYBD                           ; get keyboard character
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
        cli
        jsr             PostMsg
        ply
        plx
        pla
        rti
~
;------------------------------------------------------------------------------
; KeybdIRQ
;
; Normal keyboard interrupt, the lowest priority interrupt in the system.
; Grab the character from the keyboard device and store it in a buffer.
; The buffer of the task with the input focus is updated.
; This IRQ has to check for the ALT-tab character and take care of
; switching the IO focus if detected. It can't be done in the KeybdGetChar
; because the app with the IO focus may not call that routine. We know for
; sure the interrupt routine will be called when a key is pressed. The
; mechanism used is to set a flag indicating a focus switch is required.
; The actual focus switch occurs when a selected to run. The reason the
; focus switch doesn't occur during the interrupt routine is that it takes
; a large number of clock cycles (the screen buffer is transferred).
;------------------------------------------------------------------------------
;
message "KeybdIRQ"

public IKeybdIRQ:
public KeybdIRQ:
        inc             keybdInIRQ
        cld
        pha
        phx
        phy
        push    r4

        lda             #15                                     ; disable further keyboard interrupts
        sta             PIC+2
        ldx             KEYBD                           ; get keyboard character
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
        txy                                                     ; 
        cli                                                     ; global interrupt enable
        bit             r3,#$800                        ; test bit #11
        bne             KeybdIRQc                       ; ignore keyup messages for now
        ld              r4,IOFocusNdx           ; get the job with the input focus
        bit             r3,#$200                        ; check for ALT-tab
        beq             KeybdIrq3
        and             r3,r3,#$FF
        cmp             r3,#TAB                         ; if we find an ALT-tab
        bne             KeybdIrq3
        inc             iof_switch
;       jsr             SwitchIOFocus
        bra             KeybdIRQc                       ; don't store off the ALT-tab character
KeybdIrq3:
        and             r3,r3,#$ff
        cmp             r3,#$FA
        bne             KeybdIrq1
        sty             JCB_KeybdAck,r4
        bra             KeybdIRQc
        ; strip out non-key keyboard responses
KeybdIrq1:
        cmp             r3,#$AA                         ; self test pass
        beq             KeybdIRQd
        cmp             r3,#$EE                         ; echo response
        beq             KeybdIRQd
        cmp             r3,#$00                         ; keyboard error
        beq             KeybdIRQd
        cmp             r3,#$FF                         ; keyboard error
        beq             KeybdIRQd
        bit             r2,#$800                        ; test bit #11
        bne             KeybdIRQc                       ; ignore keyup messages for now
KeybdIrq2:
        lda             JCB_KeybdHead,r4                        
        ina                                                     ; increment head pointer
        and             #$f                                     ; limit
        ldy             JCB_KeybdTail,r4        ; check for room in the keyboard buffer
        cmp             r1,r3
        beq             KeybdIRQc                       ; if no room, the newest char will be lost
        sta             JCB_KeybdHead,r4
        dea
        and             #$f
        stx             JCB_KeybdLocks,r4
        stx             keybdLock                       ; global keyboard lock status
        add             r1,r1,r4
        stx             JCB_KeybdBuffer,r1      ; store character in buffer
KeybdIRQc:

        ; support EhBASIC's IRQ functionality
        ; code derived from minimon.asm
        lda             #15                             ; Keyboard is IRQ #15
        sta             IrqSource       
        lb              r1,IrqBase              ; get the IRQ flag byte
        lsr             r2,r1
        or              r1,r1,r2
        and             #$E0
        sb              r1,IrqBase              ; save the new IRQ flag byte
KeybdIRQd:
        lda             #15                             ; re-enable keyboard interrupts
        sta             PIC+3
        pop             r4
        ply
        plx
        pla
        dec             keybdInIRQ
        rti


public KeybdRstIRQ:
        jmp             start

;-----------------------------------------------------------------------------
; Media Check
;       A value of 1 is returned indicating that the media hasn't changed.
;-----------------------------------------------------------------------------
;
KeybdMediaChk:
        lda             #1
        rts

;-----------------------------------------------------------------------------
; r1 0=echo off, non-zero = echo on
;------------------------------------------------------------------------------
public SetKeyboardEcho:
        pha
        phx
        tax
        jsr             GetPtrCurrentJCB
        stx             JCB_KeybdEcho,r1
        plx
        pla
        rts

;------------------------------------------------------------------------------
; Get character from keyboard buffer
; return character in acc or -1 if no
; characters available.
;------------------------------------------------------------------------------
;
message "KeybdGetChar"

comment ~
public KeybdGetChar:
        phx
        phy
        push    r4
        ; Send a message to the keyboard service requesting a character.
        lda             keybd_mbx               ;
        ldx             #DCMD_GETCHAR   ; opcode
        ldy             RunningTCB              ; response mailbox number
        jsr             SendMsg
        ; Wait for a response message from the keyboard service.
        tya
        ldx             #-1
        jsr             WaitMsg
        txa
        pop             r4
        ply
        plx
        rts
~
;------------------------------------------------------------------------------
; KeybdGetChar
;
;       Get keyboard character from buffer for the current job.
;
; Registers Affected: r1, flags
; Parameters: none
; Returns:
;       r1 = keyboard character or -1 if no character is available.
;------------------------------------------------------------------------------
;
public KeybdGetChar:
        jsr             GetCurrentJob

;------------------------------------------------------------------------------
; Get keyboard character from buffer for the specified job. This entry point
; is meant to be called by the keyboard service.
;
; Registers Affected: r1, flags
; Parameters:
;       r1 = job number
; Returns:
;       r1 = keyboard character or -1 if no character is available.
;------------------------------------------------------------------------------
;
IKeybdGetChar:
        phx
        phy
        ld              r0,keybdIsSetup ; the system might call GetChar before the keyboard
        beq             .nochar                 ; is setup.
        tay
        cmp             r3,#NR_JCB
        bhs             .nochar
        mul             r3,r3,#JCB_Size         ; convert handle to pointer
        add             r3,r3,#JCBs
        lda             #15                                     ; disable keyboard interrupt
        sta             PIC+2
        ld              r0,keybdInIRQ
        bne             .nochari
        ldx             JCB_KeybdTail,y         ; if keybdTail==keybdHead then there are no 
        lda             JCB_KeybdHead,y         ; characters in the keyboard buffer
        cmp             r1,r2
        beq             .nochari
        phx
        add             r2,r2,r3
        lda             JCB_KeybdBuffer,x
        plx
        and             r1,r1,#$ff              ; mask off control bits
        inx                                             ; increment index
        and             r2,r2,#$0f
        stx             JCB_KeybdTail,y
        ldx             JCB_KeybdEcho,y
        php
        ldx             #15                             ; re-enable keyboard interrupt
        stx             PIC+3
        plp
        beq             .xit                    ; status from the ldx
        cmp             #CR
        bne             .dispchar
        jsr             CRLF                    ; convert CR keystroke into CRLF
        bra             .xit
.dispchar:
        jsr             DisplayChar
        bra             .xit
.nochari
        lda             #15                             ; re-enable keyboard interrupt
        sta             PIC+3
.nochar:
        lda             #-1
.xit:
        ply
        plx
        rts

;------------------------------------------------------------------------------
; Check if there is a keyboard character available in the keyboard buffer.
;
; Returns
; r1 = n, Z=0 if there is a key available, otherwise
; r1 = 0, Z=1 if there is not a key available
;------------------------------------------------------------------------------
;
message "KeybdCheckForKey"
public KeybdCheckForKey:
        phx
        phy
        ldx             #0
        ld              r0,keybdIsSetup
        beq             .nochar2
        jsr             GetPtrCurrentJCB
        tay
        lda             #15                             ; disable keyboard interrupt
        sta             PIC+2
        ld              r0,keybdInIRQ
        bne             .nochar
        ldx             JCB_KeybdTail,y
        sub             r2,r2,JCB_KeybdHead,y
.nochar
        lda             #15                             ; re-enable keyboard interrupt
        sta             PIC+3
.nochar2
        txa
        ply
        plx
        cmp             #0
        rts

;------------------------------------------------------------------------------
; Tests the keyboard port directly.
; Check if there is a keyboard character available. If so return true (1)
; otherwise return false (0) in r1.
;------------------------------------------------------------------------------
;
message "KeybdCheckForKeyDirect"
public KeybdCheckForKeyDirect:
        lda             KEYBD
        and             #$8000
        beq             kcfkd1
        lda             #1
kcfkd1
        rts

;------------------------------------------------------------------------------
; Get character directly from keyboard. This routine blocks until a key is
; available.
;------------------------------------------------------------------------------
;
public KeybdGetCharDirect:
        phx
kgc1:
        lda             KEYBD
        bit             #$8000
        beq             kgc1
        ld              r0,KEYBD+1              ; clear keyboard strobe
        bit             #$800                   ; is it a keydown event ?
        bne             kgc1
;       bit             #$200                           ; check for ALT-tab
;       bne             kgc2
;       and             r2,r1,#$7f
;       cmp             r2,#TAB                                 ; if we find an ALT-tab
;       bne             kgc2
;       jsr             SwitchIOFocus
;       bra             kgc1
;kgc2:
        and             #$ff                    ; remove strobe bit
        ldx             KeybdEcho               ; is keyboard echo on ?
        beq             gk1
        cmp             #CR
        bne             gk2                             ; convert CR keystroke into CRLF
        jsr             CRLF
        bra             gk1
gk2:
        jsr             DisplayChar
gk1:
        plx
        rts


;------------------------------------------------------------------------------
; Keyboard LEDs task
;       This small task tracks the keyboard lock status keys and updates the 
; keyboard LEDs accordingly. This task runs every 100ms.
;------------------------------------------------------------------------------
;
public KeybdStatusLEDs:
ksl4:
        lda             #15                             ; disable keyboard interrupt
        sta             PIC+2
        ld              r0,keybdInIRQ
        bne             ksl5
        lda             #$ED
        jsr             SendByteToKeybd
        jsr             WaitForKeybdAck ; wait for a feedback char
        cmp             #$FA            ; was it an acknowledge (should be)
        beq             ksl7
        lda             #15                     ; if not, re-enable keyboard, wait till next time
        sta             PIC+3
        bra             ksl5
ksl7:
        lda             #0
        ldx             keybdLock
        bit             r2,#4000        ; bit 14 = scroll lock status
        beq             ksl1
        lda             #1
ksl1:
        bit             r2,#1000        ; bit 12 = numlock status
        beq             ksl2
        or              r1,#2
ksl2:
        bit             r2,#2000        ; bit 13 = capslock status
        beq             ksl3
        or              r1,#4
ksl3:
    jsr         SendByteToKeybd
    lda         #15                     ; re-enabled keyboard interrupt
    sta         PIC+3
ksl5:
        lda             #10
        jsr             Sleep
        bra             ksl4

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.