Kamikaze47,
Here is the approach I've taken with decoding a PS2 style keyboard. I'll be dishing this out in chunks. The first module is an ASM interrupt service routine that retrieves the key, does some error checking, and stuffs it into a ring buffer for later retrieval and decoding within the PBP program.
And here is the PBP equates (please forgive me if I've missed any) and initialization code:Code:'=========================================================================== ' Interrupt Handler (Low Priority) '=========================================================================== ' Keyboard "getkey" handler ; KB_getkey ; Keyboard to Host Protocol ; ___ _ _ _ _ _ _ _ _ _ _ ___ ; CLOCK |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| ; ; DATA | S | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | P | E | ; ; S = start bit = 0 P = odd parity E = stop bit = 1 ; data valid on falling edge of clock ' The getkey handler responds to a high-to-low transition of the KBCLK line, ' which is the INT2 interrupt connection. Each time this occurs, data bits ' coming in through the KBDAT line (RB4) are temporarily stored in the KBcode ' variable. When a valid stop bit has been received, the data is transferred ' to a ring buffer KBbuf. This information will be later extracted by the ' PicBasic routine mod_keybd.bas and translated into ASCII and ASCIIE code. '=========================================================================== asm myintL ; save the state of critical registers movwf wsave ; Save W swapf STATUS,W ; Swap STATUS to W clrf STATUS ; bank 0, regardless of current bank movwf ssave ; Save swapped STATUS ; save the FSR value because it gets changed below movf FSR0L, W movwf fsave movf FSR0H, W movwf fsave+1 ;=========================================================================== ;AT Keyboard Service Routine ;*** check start bit *** KB_getkey movf _KBcnt,W ; check keyboard scan code bit counter bnz KB_getdat ; branch if not zero (start bit) btfsc _KBDAT ; test start bit of keyboard data input goto KB_abort ; no valid start bit, abort goto KB_exit ; exit ;*** keyboard scan code acquisition *** KB_getdat movf _KBcnt,W ; get keyboard scan code bit counter sublw d'8' ; w = d'8' - KBDcnt (*) bnc KB_parity ; branch if negative (carry == 0) btfss _KBDAT ; Test keyboard data input bcf _KBcode,7 ; clear bit 7 if KBDAT = 0 btfsc _KBDAT ; Test keyboard data input bsf _KBcode,7 ; set bit 7 if KBDAT = 1 bz KB_exit ; exit on zero (zero flag still valid from (*)) rrncf _KBcode,F ; shift new bits right (do this only 7 times) goto KB_exit ; exit ;*** check for parity and stop bit *** KB_parity movf _KBcnt,W ; get keyboard scan code counter sublw d'9' ; w = d'9' - KBDcnt bnc KB_stop ; branch if negative (carry == 0) goto KB_exit ; ignore parity bit ;*** check stop bit *** KB_stop btfss _KBDAT ; check if stop bit is valid goto KB_abort ; if not set, abort ;*** increment the buffer input index & test for buffer overrun *** incf _KBindxI,W subwf _KBindxO,W ; subtract indexes to test buffer btfsc STATUS,Z ; check for zero (KBindxI = KBindxO) goto KB_stall ; if error stall keyboard ;*** increment the buffer input index *** incf _KBindxI,F movf _KBindxI,W sublw _KBbufsize-1 ; test if index is outside the ring buffer btfss STATUS,C ; if it is... clrf _KBindxI ; reset it ; Set FSR0 with the location of the next empty location in buffer LFSR FSR0, _KBbuf ; set counter base address ; Read and store the character from the USART movf _KBindxI, W ; W = offset value for the next empty location movff _KBcode, PLUSW0 ; Move the character in KBcode to address (FSR0+W) ;*** stall keyboard *** ; to prevent the arrival of more data before having finished decoding KB_stall ; hold keyboard (with keyboard clk low): bcf TRISB,2 ; set clkline to output (back to input externally) bcf _KBCLK ; set keyboard clk line low (stall) bcf _INT2IE ; disable keyboard IRQ (re-enabled externally) goto KB_term ; terminate successfully KB_abort clrf _KBcode ; abort / invalid data KB_term clrf _KBcnt ; reset keyboard scan code acquisition counter goto KB_end ; terminate execution of keyboard IRQ KB_exit incf _KBcnt,F ; increment acquisition counter KB_end bcf _INT2IF ; clear INT2 interrupt flag ;restore registers movf fsave, W movwf FSR0L movf fsave+1, W movwf FSR0H swapf ssave,W ; Retrieve the swapped STATUS value movwf STATUS ; Restore it to STATUS swapf wsave,F ; Swap the stored W value swapf wsave,W ; Restore it to W retfie ; Return from the interrupt endasm
The nice thing about using the assembly interrupt routine, is that there will be very little overhead to the PBP part of the program, and no matter how busy it gets, you will never miss a key.Code:' PIC18F series processor used DEFINE OSC 40 DEFINE INTLHAND myintL '=========================================================================== ' Equates '=========================================================================== 'Variables for saving state in interrupt handler wsave VAR BYTE bankA system ' Saves W ssave VAR BYTE bankA system ' Saves STATUS fsave VAR WORD bankA system ' Saves FSR0 'Keyboard (Low Priority) Interrupt Handler equates KBbufsize con 10 ' keyboard buffer size KBcnt var byte bankA ' bit counter for keyboard data KBbuf var byte[KBbufsize] bankA ' keyboard ring buffer KBindxI var byte bankA ' keyboard buffer Input index pointer KBindxO var byte bankA ' keyboard buffer Output index pointer KBcode var byte bankA ' temporary storage for scan code 'Ketboard Handler equates LED var byte scrlock var LED.0 ' If true, scroll lock is on (active) numlock var LED.1 ' If true, num lock is on (active) caplock var LED.2 ' If true, caps lock is on (active) pscrlck var LED.3 ' If true, scroll lock pressed pnumlck var LED.4 ' If true, numlock pressed pcaplck var LED.5 ' If true, caps lock pressed keystat var byte Lshift var keystat.0 ' If true, left Shift pressed Rshift var keystat.1 ' If true, right Shift pressed L_ctrl var keystat.2 ' If true, left Ctrl pressed R_ctrl var keystat.3 ' If true, right Ctrl pressed L_alt var keystat.4 ' If true, left Alt pressed R_alt var keystat.5 ' If true, right Alt pressed keydec var keystat.6 ' If true, a key has been decoded scancode var byte ' temporary storage for raw keyboard scan code keycode var byte ' temporary storage for converted scancode ascii var byte ' temporary storage for Ascii equivalent parity var byte ' used during getkey for Parity tracking bitcnt var byte ' bit counter for putkey routines shift var bit ' If true, either shift key is pressed ctrl var bit ' If true, either control key is pressed alt var bit ' If true, either alt key is pressed KBrelease var bit ' flags the release of a standard key KBextend var bit ' flags that an extended key has been pressed KBrelextend var bit ' flags the release of an extended key enav var bit ' flags navigation key as extended version KB_timeout var byte TOvalue con $FF TOcntDLY con 10 '=========================================================================== ' Intitialize keyboard module, check for keyboard presence, and enable IRQ '=========================================================================== 'Check for presence of keyboard startupKB: init = 1 Gosub modstart_KBinit ' initialize & start keyboard module If KB_timeout = TOvalue Then ; *** error code goes here *** (keyboard not present on start-up) Endif Pause 1000 'Set-up Interrupts INTEDG2 = 0 ' INT2 (KBCLK) interrupt on falling edge INT2IP = 0 ' INT2 (KBCLK) set as low priority interrupt INT2IF = 0 ' INT2 (KBCLK) clear flag INT2IE = 1 ' INT2 (KBCLK) interrupt enabled IPEN = 1 ' Enable priority levels on interrupts INTCON = %11000000 ' Enable all interrupts! '=========================================================================== ' Program Start (MAIN) '=========================================================================== mainloop: Gosub KBmain ' checking for keyboard activity... ' and decode any incoming characters. ' --------------------------------- ' ' program code here --- KBmain will return result in ascii variable ' ' --------------------------------- Goto mainloop
If you are interested in seeing more, then on the next installment I'll post the KBmain code (decodes keyscan codes), followed by the lookup table. Please let me know
Cheers,





Bookmarks