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 0DCMD_MEDIA_CHK EQU 1DCMD_BUILD_BPB EQU 2DCMD_IOCTRL_READ EQU 3DCMD_READ EQU 4DCMD_PEEK EQU 5DCMD_INPUT_STATUS EQU 6DCMD_FLUSH_INPUT EQU 7DCMD_WRITE EQU 8DCMD_WRITE_VERIFY EQU 9DCMD_OUTPUT_STATUS EQU 10DCMD_FLUSH_OUTPUT EQU 11DCMD_IOCTRL_WRITE EQU 12DCMD_OPEN EQU 13DCMD_CLOSE EQU 14DCMD_IS_REMOVEABLE EQU 15DCMD_OUTPUT_UNTIL_BUSY EQU 16DCMD_IRQ EQU 0xFFFFFFFDDCMD_GETCHAR EQU 32DRSP_DONE EQU 1cpu RTF65002.code;------------------------------------------------------------------------------; The keyboard interrupt is selectively disabled and enabled to protect; the keyboard buffers structure. Other interrupts are still enabled.;------------------------------------------------------------------------------macro DisKeybdphalda #15sta PIC+2plaendmmacro EnKeybdphalda #15sta PIC+3plaendmalign 4; Device driver structdw 0xFFFFFFFF ; link to next devicedw 0x00008001 ; device attributesdw KeybdStrategy ; strategy routinedw KeybdIRQ ; interrupt routinedw KeybdCmdProc ; command processoralign 4dw KeybdNopdw KeybdInitdw KeybdMediaChkdw KeybdBuildBPBdw KeybdGetChar ; GetChar()dw KeybdCheckForKey ; PeekChar()dw KeybdGetCharDirect ; unbuffered GetChar()dw KeybdCheckForKeyDirect ; unbuffered PeekChar()dw SendByteToKeybd ; KeybdPutChardw SetKeyboardEchodw KeybdSetpos ; set position;------------------------------------------------------------------------------;------------------------------------------------------------------------------public KeybdDCB:align 4db "KBD1 " ; namedw 4 ; number of chars in namedw 1 ; typedw 1 ; nBPBdw 0 ; last ercdw 0 ; nBlocksdw KeybdCmdProcdw KeybdInitdw KeybdStatdw 1 ; reentrancy count (1 to 255 are valid)dw 0 ; single userdw 0 ; hJobdw 0 ; OSD1dw 0 ; OSD2dw 0 ; OSD3dw 0 ; OSD4dw 0 ; OSD5dw 0 ; OSD6KeybdStrategy:rtsKeybdCmdProc:rtsKeybdStat:rtsKeybdBuildBPB:rtsKeybdSetpos:rtsKeybdNop:lda #E_Okrts;------------------------------------------------------------------------------; 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 semaphoresta keybd_semalda #32sta LEDSldx #0; Set Keyboard IRQ vectortsr vbr,r2and r2,#-2lda #KeybdIRQsta 448+15,xlda #15 ; enable kbd_irqsta PIC+3jsr KeybdInitlda #1 ; keyboard is device #1ldx #KeybdDCB ; pointer to DCBldy #1 ; number of DCB's to setupld r4,#1 ; Flag: is okay to replace existing device; jsr InitDevDrvstz keybdInIRQinc keybdIsSetup ; set the setup flagrtsKeybdInit:lda #33sta LEDSlda #$ff ; issue keyboard resetjsr SendByteToKeybdlda #38sta LEDSlda #4; jsr Sleeplda #1000000 ; delay a bitkbdi5:deasta LEDSbne kbdi5lda #34sta LEDSlda #0xf0 ; send scan code selectjsr SendByteToKeybdlda #35sta LEDSldx #0xFAjsr WaitForKeybdAckcmp #$FAbne kbdi2lda #36sta LEDSlda #2 ; select scan code set#2jsr SendByteToKeybdlda #39sta LEDSkbdi2:rtsmsgBadKeybd:db "Keyboard not responding.",0SendByteToKeybd:phxldx IOFocusNdxsta KEYBDlda #40sta LEDStsr TICK,r3kbdi4: ; wait for transmit completetsr TICK,r4sub r4,r4,r3cmp r4,#1000000bhi kbdbadlda #41sta LEDSlda KEYBD+3bit #64beq kbdi4bra sbtk1kbdbad:lda #42sta LEDSlda JCB_KeybdBad,xbne sbtk2lda #1sta JCB_KeybdBad,xlda #43sta LEDSlda #msgBadKeybdjsr DisplayStringCRLFBsbtk1:lda #44sta LEDSplxrtssbtk2:bra sbtk1; Wait for keyboard to respond with an ACK (FA);WaitForKeybdAck:lda #64sta LEDStsr TICK,r3wkbdack1:tsr TICK,r4sub r4,r4,r3cmp r4,#1000000bhi wkbdbadlda #65sta LEDSlda KEYBDbit #$8000beq wkbdack1; lda KEYBD+8and #$ffwkbdbad: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:phyldy IOFocusNdxWaitForKeybdAck2a:lda JCB_KeybdAck,ycmp r1,r2bne WaitForKeybdAck2astz JCB_KeybdAck,yplyrts;------------------------------------------------------------------------------; Code in the works.;------------------------------------------------------------------------------;comment ~public KeybdService:lda #keybd_mbxjsr AllocMbxjsr KeybdSetupkbds3:; Wait for a message to arrive at the servicelda keybd_mbxldx #-1 ; wait foreverjsr WaitMsgcpx #DCMD_IRQbeq kbds1cpx #DCMD_GETCHARbeq kbds2cpx #DCMD_INITIALIZEbeq kbds4bra kbds3kbds1:tyx ; D2 holds characterjsr IKeybdIRQbra kbds3kbds2:; The mailbox number is the same as the TCB numbertyajsr IKeybdGetChar; Send a message back to the requester containing the key value.taxtyaldy #0jsr SendMsgbra kbds3kbds4:jsr KeybdInitbra kbds3~comment ~public XKeybdIRQ:phaphxphylda keybd_mbxldx #DCMD_IRQldy KEYBD ; get keyboard characterld r0,KEYBD+1 ; clear keyboard strobe (turns off the IRQ)clijsr PostMsgplyplxplarti~;------------------------------------------------------------------------------; 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 keybdInIRQcldphaphxphypush r4lda #15 ; disable further keyboard interruptssta PIC+2ldx KEYBD ; get keyboard characterld r0,KEYBD+1 ; clear keyboard strobe (turns off the IRQ)txy ;cli ; global interrupt enablebit r3,#$800 ; test bit #11bne KeybdIRQc ; ignore keyup messages for nowld r4,IOFocusNdx ; get the job with the input focusbit r3,#$200 ; check for ALT-tabbeq KeybdIrq3and r3,r3,#$FFcmp r3,#TAB ; if we find an ALT-tabbne KeybdIrq3inc iof_switch; jsr SwitchIOFocusbra KeybdIRQc ; don't store off the ALT-tab characterKeybdIrq3:and r3,r3,#$ffcmp r3,#$FAbne KeybdIrq1sty JCB_KeybdAck,r4bra KeybdIRQc; strip out non-key keyboard responsesKeybdIrq1:cmp r3,#$AA ; self test passbeq KeybdIRQdcmp r3,#$EE ; echo responsebeq KeybdIRQdcmp r3,#$00 ; keyboard errorbeq KeybdIRQdcmp r3,#$FF ; keyboard errorbeq KeybdIRQdbit r2,#$800 ; test bit #11bne KeybdIRQc ; ignore keyup messages for nowKeybdIrq2:lda JCB_KeybdHead,r4ina ; increment head pointerand #$f ; limitldy JCB_KeybdTail,r4 ; check for room in the keyboard buffercmp r1,r3beq KeybdIRQc ; if no room, the newest char will be loststa JCB_KeybdHead,r4deaand #$fstx JCB_KeybdLocks,r4stx keybdLock ; global keyboard lock statusadd r1,r1,r4stx JCB_KeybdBuffer,r1 ; store character in bufferKeybdIRQc:; support EhBASIC's IRQ functionality; code derived from minimon.asmlda #15 ; Keyboard is IRQ #15sta IrqSourcelb r1,IrqBase ; get the IRQ flag bytelsr r2,r1or r1,r1,r2and #$E0sb r1,IrqBase ; save the new IRQ flag byteKeybdIRQd:lda #15 ; re-enable keyboard interruptssta PIC+3pop r4plyplxpladec keybdInIRQrtipublic KeybdRstIRQ:jmp start;-----------------------------------------------------------------------------; Media Check; A value of 1 is returned indicating that the media hasn't changed.;-----------------------------------------------------------------------------;KeybdMediaChk:lda #1rts;-----------------------------------------------------------------------------; r1 0=echo off, non-zero = echo on;------------------------------------------------------------------------------public SetKeyboardEcho:phaphxtaxjsr GetPtrCurrentJCBstx JCB_KeybdEcho,r1plxplarts;------------------------------------------------------------------------------; Get character from keyboard buffer; return character in acc or -1 if no; characters available.;------------------------------------------------------------------------------;message "KeybdGetChar"comment ~public KeybdGetChar:phxphypush r4; Send a message to the keyboard service requesting a character.lda keybd_mbx ;ldx #DCMD_GETCHAR ; opcodeldy RunningTCB ; response mailbox numberjsr SendMsg; Wait for a response message from the keyboard service.tyaldx #-1jsr WaitMsgtxapop r4plyplxrts~;------------------------------------------------------------------------------; 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:phxphyld r0,keybdIsSetup ; the system might call GetChar before the keyboardbeq .nochar ; is setup.taycmp r3,#NR_JCBbhs .nocharmul r3,r3,#JCB_Size ; convert handle to pointeradd r3,r3,#JCBslda #15 ; disable keyboard interruptsta PIC+2ld r0,keybdInIRQbne .nocharildx JCB_KeybdTail,y ; if keybdTail==keybdHead then there are nolda JCB_KeybdHead,y ; characters in the keyboard buffercmp r1,r2beq .nochariphxadd r2,r2,r3lda JCB_KeybdBuffer,xplxand r1,r1,#$ff ; mask off control bitsinx ; increment indexand r2,r2,#$0fstx JCB_KeybdTail,yldx JCB_KeybdEcho,yphpldx #15 ; re-enable keyboard interruptstx PIC+3plpbeq .xit ; status from the ldxcmp #CRbne .dispcharjsr CRLF ; convert CR keystroke into CRLFbra .xit.dispchar:jsr DisplayCharbra .xit.nocharilda #15 ; re-enable keyboard interruptsta PIC+3.nochar:lda #-1.xit:plyplxrts;------------------------------------------------------------------------------; 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:phxphyldx #0ld r0,keybdIsSetupbeq .nochar2jsr GetPtrCurrentJCBtaylda #15 ; disable keyboard interruptsta PIC+2ld r0,keybdInIRQbne .nocharldx JCB_KeybdTail,ysub r2,r2,JCB_KeybdHead,y.nocharlda #15 ; re-enable keyboard interruptsta PIC+3.nochar2txaplyplxcmp #0rts;------------------------------------------------------------------------------; 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 KEYBDand #$8000beq kcfkd1lda #1kcfkd1rts;------------------------------------------------------------------------------; Get character directly from keyboard. This routine blocks until a key is; available.;------------------------------------------------------------------------------;public KeybdGetCharDirect:phxkgc1:lda KEYBDbit #$8000beq kgc1ld r0,KEYBD+1 ; clear keyboard strobebit #$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 bitldx KeybdEcho ; is keyboard echo on ?beq gk1cmp #CRbne gk2 ; convert CR keystroke into CRLFjsr CRLFbra gk1gk2:jsr DisplayChargk1:plxrts;------------------------------------------------------------------------------; 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 interruptsta PIC+2ld r0,keybdInIRQbne ksl5lda #$EDjsr SendByteToKeybdjsr WaitForKeybdAck ; wait for a feedback charcmp #$FA ; was it an acknowledge (should be)beq ksl7lda #15 ; if not, re-enable keyboard, wait till next timesta PIC+3bra ksl5ksl7:lda #0ldx keybdLockbit r2,#4000 ; bit 14 = scroll lock statusbeq ksl1lda #1ksl1:bit r2,#1000 ; bit 12 = numlock statusbeq ksl2or r1,#2ksl2:bit r2,#2000 ; bit 13 = capslock statusbeq ksl3or r1,#4ksl3:jsr SendByteToKeybdlda #15 ; re-enabled keyboard interruptsta PIC+3ksl5:lda #10jsr Sleepbra ksl4
