PDA

View Full Version : AT/PS2 Keybord - PIC Interface?



Kamikaze47
- 6th November 2005, 18:30
Has anyone ever interfaced an AT or PS2 keyboard to a PIC that might be able to give me an idea on how to set it up?

I know that the keyboard has data and clock lines which i will obviously have to hook up to a couple of the PICs I/O pins, but im not sure how to use pbp to recieve the data.

Any help would be greatly apreciated.

*edit* Im using a PIC16F84A

Kamikaze47
- 6th November 2005, 18:53
After looking thought the pbp manual im thinking the SHIFTIN *might* do the trick?

What u guys recon?

Ron Marcus
- 7th November 2005, 11:34
Search the archives, there are some good links there. Also, Shiftin is a master routine. You need a slave routine to work with the keyboard. Tom Enghdahl's? site has some excellent info on the interfacing of a uP to a keyboard. Alas, it's in assembly, but it is fairly easy to translate to PBP.

Ron

Kamikaze47
- 7th November 2005, 15:09
So i take it that pbp doesnt have a slave version of shiftin?

Ron Marcus
- 7th November 2005, 15:36
So i take it that pbp doesnt have a slave version of shiftin?

Nope. You basically "sit and rotate"... Let me explain, the keyboard line has a data and a clock line. It is controlled by the keyboard clock. I don't remember, but I believe the data is valid on a high to low transition of the clock. This can be confirmed with a Google search. You will also need to know whether the data is clocked in MSB, or LSB first. The shiftin subroutine waits for the clock line to go low(?), puts the data state into the lowest bit of your variable,if MSB,and shift the variable one position to the left. This is followed by a wait for the clock line to go back high, and it is done 7 more times. You can do this in a for next loop, and the code is pretty simple.
FOR A = 1 to 8
loop1: IF clock = 1 then loop1
Key_data.0 = dataline
Key_data = Key_data *2 ; Shift once to left
loop2: IF clock = 0 then loop2
Next A
Key_data now contains the keypress value. It is not the neat Ascii representation of the character you pressed. Nooooo....Lest it be that simple! Now you must use a lookup table with the proper characters in the right order, but when you are done, you will have the right character. Right? Unless you want upper and lower case. You will have to look at the shift keypress characters and see if they are being held down, or if caps lock has been engaged. Let's not even talk about the "extended characters"!

Have fun,
Ron

Kamikaze47
- 7th November 2005, 16:24
Thanks for that Ron Marcus. Yep the data comes in when the clock does a high to low transition, is least signicant bit first, and is 11 bits long (1 start bit, 8 data bits, 1 parity bit and 1 stop bit).

So, hopefully something like this will work:

FOR A = 1 to 11
loop1: IF clock = 1 THEN GOTO loop1
IF A=1 OR A=10 or A=11 THEN GOTO loop2 'No need to store start, stop or partiy bits
Key_data.7 = dataline
Key_data = Key_data/2 'Shift once to the right
loop2: IF clock = 0 THEN GOTO loop2
NEXT A

mytekcontrols
- 8th November 2005, 03:28
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.



'================================================= ==========================
' 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


And here is the PBP equates (please forgive me if I've missed any) and initialization 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



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.

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,

Kamikaze47
- 8th November 2005, 07:47
mytekcontrols: Thanks heaps for that.

I managed to get it somewhat going without interrupts but it messes up whenever I type fast on the keyboard, so i'll give ur code a try. I'll just have to go through it all 1st to make sure I understand it :)

If you could post your code that decodes the keyscan codes that would be excellent. I tried writing my own but the code was so long that it wouldn’t fit on the PIC16F84A that im using. It may be the case that I need to go with a different PIC?

Kamikaze47
- 8th November 2005, 08:07
Also, could you post this subroutine: modstart_KBinit

Thanks

M. Tayem
- 8th November 2005, 14:29
Hi,

Although it is written for another compiler, but I am sure it can be adapted to PBP.

http://users.picbasic.org/Howto/PC_keybrd/pc_keyboard.htm


Regards
Mohammed

mytekcontrols
- 8th November 2005, 18:36
Kamikaze47:

Also, could you post this subroutine: modstart_KBinit

This is not actually a separate subroutine, but just a different entry point into the KBmain routine.

Kamikaze47:

If you could post your code that decodes the keyscan codes that would be excellent. I tried writing my own but the code was so long that it wouldn’t fit on the PIC16F84A that im using. It may be the case that I need to go with a different PIC?

I should warn you :eek: Doing a full decode of a PS2 keyboard is not trivial, and does require a substantial amount of code. There are shortcuts, but usually this will leave you without many of the features people come to expect from these style of keyboards. The first problem is that the keyscan codes as they are called, do not follow a very logical pattern. This was made even worse by the evolution from the older 84 key keyboards to the modern 104+ key keyboards. It is really unfortunate that a better standard wasn't developed early on.

To develop my decode routines; I first did as you probably have done, looked around the net for something that was close. There is a lot of info out there, but not too much that is geared towards a PIC, and nothing I could find that would do it in PBP. What I did find, and which was my inspiration, is this piece from Craig Peacock written in 1998 for a 68HC705 Interfacing the AT keyboard (http://www.beyondlogic.org/keyboard/keybrd.htm). Understandably it is written for an entirely different processor (CISC instead of RISC), but I had a good grounding in 6502 from my early Atari days as a hobbiest assembly language programmer, and this was fairly close to 68HC705 syntax. So I initially took on the task of translating the 68HC705 code over to PBP. The end result worked, but it was massive!

The next step of the process was one of refinement. The biggest memory drain were the extensive tables required in order to decode the convoluted keyscan code mess, into usable ascii codes. I decided what was needed first and foremost was to transform the keyscan codes into something more sequential, without all the gaps and disorder of the original. This way much of the decoding could then be done through purely mathamatically methods of adding or subtracting an offset value in order to get an ascii number code that equated to a given key or ctrl+key/shift+key combination. I ended up calling my keyscan translation "keycodes". Here is a look at both the keycodes and the ascii mapping that I used (includes extended numbers for non-ascii keypresses such as the function keys): KEYS.pdf (http://www.picbasic.co.uk/forum/attachment.php?attachmentid=601&stc=1&d=1131472366).

And here is the actual table code utilized:


keycode_tbl:
asm
movlw Low keycode_tbl
movff WREG, _ktable
movlw High keycode_tbl
movff WREG, _ktable + 1
endasm

Readcode ktable + scancode, keycode
Return

asm
keycode_tbl
DB 0x80,0x39,0x80,0x35,0x33,0x31,0x32,0x3C
DB 0x80,0x3A,0x38,0x36,0x34,0x80,0x1B,0x80
DB 0x80,0x80,0x80,0x80,0x80,0x11,0x21,0x80
DB 0x80,0x80,0x1A,0x13,0x01,0x17,0x22,0x3D
DB 0x80,0x03,0x18,0x04,0x05,0x24,0x23,0x3E
DB 0x80,0x80,0x16,0x06,0x14,0x12,0x25,0x3F
DB 0x80,0x0E,0x02,0x08,0x07,0x19,0x26,0x80
DB 0x80,0x80,0x0D,0x0A,0x15,0x27,0x28,0x80
DB 0x80,0x2D,0x0B,0x09,0x0F,0x20,0x29,0x80
DB 0x80,0x2E,0x2F,0x0C,0x2B,0x10,0x1C,0x80
DB 0x80,0x80,0x2C,0x80,0x1E,0x1D,0x80,0x80
DB 0x80,0x80,0x80,0x1F,0x80,0x2A,0x80,0x80
DB 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
DB 0x80,0x41,0x80,0x44,0x47,0x80,0x80,0x80
DB 0x40,0x4A,0x42,0x45,0x46,0x48,0x30,0x80
DB 0x3B,0x4D,0x43,0x4C,0x4B,0x49,0x80,0x80
DB 0x80,0x80,0x80,0x37
endasm


noshift_tbl:
asm
movlw Low noshift_tbl
movff WREG, _ktable
movlw High noshift_tbl
movff WREG, _ktable + 1
endasm

Goto keytrans

asm
noshift_tbl
DB "`","-","=","[","]","0","1","2"
DB "3","4","5","6","7","8","9",0x5C
DB ";","'",",",".","/",0x1B,0x7F,"*"
DB "-","+"
endasm


shift_tbl:
asm
movlw Low shift_tbl
movff WREG, _ktable
movlw High shift_tbl
movff WREG, _ktable + 1
endasm

Goto keytrans

asm
shift_tbl
DB "~","_","+","{","}",")","!","@"
DB "#","$","%","^","&","*","(","|"
DB ":",0x22,"<",">","?",0xA0,0xBF,"*"
DB "-","+"
endasm


ctrl_tbl:
asm
movlw Low ctrl_tbl
movff WREG, _ktable
movlw High ctrl_tbl
movff WREG, _ktable + 1
endasm

keytrans:
Readcode ktable + (keycode - $1B), ascii
Return

asm
ctrl_tbl
DB 0x00,0x1F,0xEA,0x1B,0x1D,0xE0,0xE1,0xE2
DB 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0x1C
DB 0xEB,0xEC,0xED,0xEE,0x1E,0xC0,0xDF,"*"
DB "-","+"
endasm


You'll notice if you scroll through the table code, that there are sub-tables marked as noshift, shift, and ctrl. These were required for some of the special navigation and Number Pad keys, which are part of the extended keyscan codes added during the 84 to 104 key transition period.

:( Of course wouldn't you know it, they require special handling since their actual code assignment mimics those of other existing keys (they have an additional $E0 scan code sent in order to distinguish them from standard keys).

Luckily the addition of these very small sub-tables doesn't really impact too greatly on code size requirements. Overall if you compare this table to the one used in Craig Peacock's 68HC705 code you will still see a dramatic reduction in size.

More to come <img src="http://www.picbasic.co.uk/forum/images/icons/icon2.gif" align="absmiddle"> Installment #3: KBmain module (the decoding routines)

mytekcontrols
- 8th November 2005, 23:20
Here is the 1st half of the KBmain module, which is responsible for the keyboard keyscan-to-ascii decoding process.

The KBmain Module Part A:


;================================================= ==============================
; modstart_keybd - Initialization Entry Point for Keyboard Decoding Module.
;================================================= ==============================

modstart_KBinit:
Input KBCLK ' set-up keyboard clock
Input KBDAT ' and keyboard data lines as digital inputs.
KB_timeout = 0 ' initialize some registers...
KBcnt = 0
' No attempt will be made to reset the keyboard as it
' would still be in POST or BAT tests if power were
' applied at the same time as the PIC.

;================================================= ==============================
; rstflag - Resets Status and LED Flags.
;================================================= ==============================

rstflag:
keystat = 0
LED = 0
Goto LEDshow

;================================================= ==============================
; KBmain - Main Entry Point for Keyboard Decoding Module.
;================================================= ==============================

KBmain:
If KBindxO = KBindxI Then KBexit ' if key buffer is empty then exit

' update combined shift/ctrl/alt registers from individual registers
If Lshift = 1 or Rshift =1 Then
shift = 1
Else
Shift = 0
Endif
If L_ctrl = 1 or R_ctrl =1 Then
ctrl = 1
Else
ctrl = 0
Endif
If L_alt = 1 or R_alt =1 Then
alt = 1
Else
alt = 0
Endif

' check to see if this is a key coming up
If KBrelease = 1 Then release ' release code previously sent
If KBextend = 1 Then extend ' extended code previously sent
If KBrelextend = 1 Then rel_ext ' ext/release code previously sent

' go get keyboard byte from ring buffer for interpretation
Gosub getbuf

' check for special codes
Select Case scancode
Case $F0 ' key has been released
KBrelease = 1
Goto KBexit

Case $FE ' key resend requested
Gosub putkey
Goto kbmain

Case $FF ' keyboard error
Gosub putkey
Goto rstflag

Case $AA ' successful completion of BAT
Goto rstflag

Case $E0 ' Extended key pressed
KBextend = 1
Goto KBexit

Case $29 ' Space bar pressed
ascii = $20
Goto dec_done

Case $0D ' Tab key pressed
ascii = $09
Goto dec_done

Case $66 ' Backspace key pressed
ascii = $08
Goto dec_done

Case $5A ' Enter key pressed
ascii = $0D
Goto dec_done

Case $12 ' Left shift key pressed
Lshift = 1

Case $59 ' Right shift key pressed
Rshift = 1

Case $14 ' Left Ctrl key pressed
L_ctrl = 1

Case $11 ' Left Alt key pressed
L_alt = 1

Case $58 ' Caps lock key pressed
If pcaplck = 0 Then caps
pcaplck = 1

Case $77 ' Numlock key pressed
If pnumlck = 0 Then nums
pnumlck = 1

Case $7E ' Scroll lock key pressed
If pscrlck = 0 Then scrl
pscrlck = 1
End Select

' no special codes received, so verify byte as legal
If scancode > $83 Then KBexit ' if it exceeds table boundry leave!

' translation of keyboard scan code to our keycode
Gosub keycode_tbl ' Else, translate it to keycode
If keycode = $80 Then KBexit ' Check it, and if it is un-
' decodeable then leave!
If keycode < $31 Then KBmain1 ' if true, decode for ascii
' Else, this requires some fiddling...
If keycode > $3F Then ' start of kepad number assignments
If keycode < $4A Then ' end of keypad number assignments
If numlock = 1 Then ' are we in numlock mode?
If ctrl = 0 Then ' are there no control or
If shift = 0 Then ' shift keys pressed?
keycode = keycode - $20 ' re-index for numbers 0-9
Goto KBmain1
Endif
Endif
Endif
Endif
Endif
Goto navkey

KBmain1:
' if this is a ctrl+key situation then decode as such
If ctrl = 1 Then
If keycode < $1B Then ascii = keycode ' ascii control char
If keycode > $1A Then Gosub ctrl_tbl ' special char decode
Goto dec_done
Endif

' Here is where we sort out the Caps-lock and Shift dilema, which is
' especially tricky when dealing with the Num Pad keys.
Select Case caplock
Case 0 ' cap lock OFF
If shift = 0 Then
If keycode < $1B Then ' if alphanumeric...
ascii = keycode + $60 ' convert to ascii lowercase alpha
Else ' if punctuation...
Gosub noshift_tbl ' get non-shifted value
Endif
Else
If keycode < $1B Then ' if alphanumeric...
ascii = keycode + $40 ' convert to ascii uppercase alpha
Else ' if punctuation...
Gosub shift_tbl ' get shifted value
Endif
Endif
Case 1 ' cap lock ON
If shift = 0 Then
If keycode < $1B Then ' if alphanumeric...
ascii = keycode + $40 ' convert to ascii uppercase alpha
Else ' if punctuation...
Gosub noshift_tbl ' get non-shifted value
Endif
Else
If keycode < $1B Then ' if alphanumeric...
ascii = keycode + $60 ' convert to ascii lowercase alpha
Else ' if punctuation...
Gosub shift_tbl ' get shifted value
Endif
Endif
End Select

' decoding of key is complete by the time it reaches this point
dec_done:
keydec = 1 'key decoded, set flag
Gosub modstart_prnt2scrn

' Check to see if there are any more bytes left to process in the
' ring buffer. If there is, go get it and process it!
KBexit:
If KBindxO != KBindxI Then KBmain ' more bytes left
Input KBCLK ' release clock line
INT2IE = 1 ' re-enable IRQ
Return

getbuf:
KBindxO = KBindxO + 1 ' increment index
If KBindxO => KBbufsize Then KBindxO = 0
scancode = KBbuf[KBindxO] ' fetch next scancode
Return


More to come <img src="http://www.picbasic.co.uk/forum/images/icons/icon2.gif"> Installment #3b: KBmain module (2nd half)

mytekcontrols
- 9th November 2005, 00:42
Here is the 2nd and final piece of the KBmain module, which is responsible for the keyboard keyscan-to-ascii decoding process. This code covers all the subroutines utilized within the first part.

The KBmain Module Part B:


;================================================= ==============================
; scrl - Toggle Status of Scroll lock and Echo to Keyboard
;================================================= ==============================

scrl:
pscrlck = 1 'set flag to prevent routine recall
LED = (LED ^ %001) 'toggle Scroll lock flag
Goto LEDshow

;================================================= ==============================
; nums - Toggle Status of Num lock and Echo to Keyboard.
;================================================= ==============================

nums:
pnumlck = 1 'set flag to prevent routine recall
LED = (LED ^ %010) 'toggle Num lock flag
Goto LEDshow

;================================================= ==============================
; caps - Toggle Status of Caps lock and Echo to Keyboard.
;================================================= ==============================

caps:
pcaplck = 1 'set flag to prevent routine recall
LED = (LED ^ %100) 'toggle Caps lock flag
Goto LEDshow

;================================================= ==============================
; extend - An Extended key has been pressed.
;================================================= ==============================

extend:
KBextend = 0
Gosub getbuf
Select Case scancode
Case $F0 'an extended key has been released
KBrelextend = 1
Goto KBexit

Case $11 'Right Alt pressed
R_alt = 1

Case $14 'Right Ctrl pressed
R_ctrl = 1

Case $5A 'Enter key on Numpad pressed
ascii = $0D
Goto dec_done

Case $4A '"/" on Numpad pressed
ascii = "/"
Goto dec_done

Case $71 'Delete on Nav keys pressed
keycode = $4A
Goto navkey1
End Select

If scancode > $83 Then KBexit 'exceeds table boundry
Gosub keycode_tbl 'translate to keycode
If keycode = $80 Then KBexit 'value not defined in table
If keycode < $31 Then KBexit 'not a navigation key
enav = 1
navkey:
If keycode = $45 Then KBexit 'ignore numpad 5 key
If numlock = 1 Then
If ctrl = 0 Then
If shift = 0 Then
If keycode = $4A Then ' if delete then...
ascii = "." ' make as period
Goto dec_done
Endif
Endif
Endif
Endif
If keycode < $4A Then Goto navkey2

navkey1:
keycode = keycode - $19 're-index for table read
Goto KBmain1

navkey2:
ascii = keycode + $50 'normal key
If shift = 1 Then
If enav or keycode < $40 Then
ascii = keycode + $70 'shift modified key
Else
ascii = keycode - $10 're-index for numbers 0-9
Endif
enav = 0
Endif
If ctrl = 1 Then ascii = keycode + $90 'ctrl modified key
Goto dec_done

;================================================= ==============================
; release - A Key has been Released.
;================================================= ==============================

release:
KBrelease = 0
gosub getbuf
Select Case scancode
Case $12 'Left shift key released
Lshift = 0

Case $59 'Right shift key released
Rshift = 0

Case $14 'Left Ctrl key released
L_ctrl = 0

Case $11 'Left Alt key released
L_alt = 0

Case $58 'Caps lock key released
pcaplck = 0

Case $7E 'Scroll lock key released
pscrlck = 0

Case $77 'Num lock key released
pnumlck = 0
End Select

Goto KBexit

;================================================= ==============================
; rel_ext - An Extended Key has been Released.
;================================================= ==============================

rel_ext:
KBrelextend = 0
Gosub getbuf
Select Case scancode
Case $11 'Right Alt key released
R_alt = 0

Case $14 'Right Ctrl key released
R_ctrl = 0
End Select

Goto KBexit

;================================================= ==============================
; LEDshow - Copies the 3 LSB of the LED register to the keyboard for the
; keyboard's Status LEDs (i.e.; Num Lock, Caps Lock, Scroll Lock).
;================================================= ==============================

LEDshow:
scancode = $ED
Gosub putkey
scancode = (LED & %111)
Gosub putkey
If init = 1 Then
init = 0
Return
Endif
Goto KBexit

;================================================= ==============================
; _putkey
; Host to Keyboard Protocol
; ___ _ _ _ _ _ _ _ _ _ _ _ _ ___
; CLOCK |__| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|
;
; DATA | S | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | P | E |ACK|
;
; S = start bit = 0 P = odd parity E = stop bit = 1 ACK =0
; data valid on falling edge of clock
;================================================= ==============================
putkey:
parity = 1 'set-up parity register (odd parity)

'Let's initiate a com request to the keyboard.

Low KBCLK 'pull clock line low.
Pauseus 35 'pause 35uSec...
Low KBDAT 'pull data line low.
Pauseus 125 'pause 125uSec longer...
Input KBCLK 'then release the clock line.

'we have now signaled the keyboard
'that we wish to send data to it
'so let's do it!

For bitcnt = 1 To 8 'set for 8 data bits
Gosub sendbit 'send DATA BIT
If scancode.0 = 0 Then nextbit 'if not a 1 then continue
parity = parity + 1 'else, add up total # of 1's
nextbit:
scancode = scancode >> 1 'shift out next bit
Next bitcnt
scancode.0 = parity.0
Gosub sendbit 'send PARITY BIT
scancode.0 = 1
Gosub sendbit 'send STOP BIT
'all data bits sent so...
Input KBDAT 'release the data line
Pauseus 100 'and wait for ACK BIT to pass.
Return 'DONE --- Scancode sent to keyboard!!!


sendbit:
' time-out counter --- requires keyboard response, else bail out!
Pauseus TOcntDLY 'determines delay for each count
KB_timeout = KB_timeout + 1
If KB_timeout = TOvalue Then
Return
Endif

' looking for keyboard clock line to go low, then send data bit to it!
If KBCLK = 1 Then sendbit 'loop until clock line goes low
KBDAT = scancode.0 'send data bit
KB_timeout = 0
clkhigh:
If KBCLK = 0 Then clkhigh 'loop until clock line goes high
Return



Here are the port I/O assignments that I used on my PIC18F2525:


KBCLK VAR PORTB.2 ; INT2
KBDAT VAR PORTB.3


Actually any port pin can be used for the KBDAT I/O, and any port pin capable of generating an interrupt on a high-to-low transition could be used for KBCLK (with the proper changes in the interrupt code). Both ports are used for bi-directional communications with the keyboard, and should both be provided with 4.7K pull-up resistors to +5 Vdc. No initialization is required for either of these ports (it is all handled from within the KBmain module).

Here is the pin-out for the mini-din plug used on a typical PS2 keyboard (I hope those guys in the Proton area don't mind me borrowing this):
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=603&stc=1&d=1131493312">

And here is a test routine to see if everything is working properly:


DEFINE HSER_TXSTA 20h
DEFINE HSER_BAUD 9600

A var byte
B var byte
temp var byte

'============================================
' Test Routine
'============================================
mainloop:
Gosub KBmain ' Do keyboard decode routine and if
' a key has been pressed then a jump
' will be made to "modstart_prnt2scrn".
Goto mainloop ' Else, keep looping!


modstart_prnt2scrn:
If keydec Then ' check if decoded key is present
keydec = 0 ' If so... reset key decoded flag,
Gosub dec2hex ' create 2 digit hex value from ascii,
' and send formatted info out RS232.

' serial output example: ascii = A ($41)

hserout["ascii = ",ascii," ($",A,B,")",$0D,$0A]
Endif
Return


dec2hex:
temp = ascii/16
Gosub dec2hex_tbl
A = temp
temp = ascii//16
Gosub dec2hex_tbl
B = temp
Return
dec2hex_tbl:
Lookup temp,["0123456789ABCDEF"],temp
Return


And this concludes the last of our series on Interfacing a PS2 Keyboard to your PIC :)

P.S. Let me know if I missed something. I all stripped this stuff out of a much larger program that I wrote, and hopefully I got all the bits.

Kamikaze47
- 9th November 2005, 07:50
Thanks heaps for that mytekcontrols. I really appreciate it :)

Now to go thru all the code and work out what its doing :)

I'll let u know how I go.

mytekcontrols
- 9th November 2005, 19:39
I hope it all works for you.

Here are some additional items to note:

If the code is used "as is" on a PIC18F type chip, then the following equates will probably need to be included:


TMR0IP VAR INTCON2.2 ' TMR0 overflow interrupt priority bit
INTEDG2 VAR INTCON2.4 ' External interrupt-2 edge select bit
INT2IF VAR INTCON3.1 ' INT2 external interrupt flag
INT2IE VAR INTCON3.4 ' INT2 external interrupt enable
IPEN VAR RCON.7 ' Interrupt priority enable


Also if not using priority interrupts (another 18F feature) it will be necessary to change the define from "DEFINE INTLHAND myintL" to "DEFINE INTHAND myintL", and of course some of the following parameters will need to be changed to match your situation:


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!



If you're not using an 18F series PIC, then some of the following might apply:


In the interrupt routine; there is a syntax problem. Below you will see 2 lines listed. The first is the currently used one in the interrupt routine. The second is the correct one to use on something other then an 18F series device (PIC16..., PIC17...).


rrncf _KBcode,F ; shift new bits right (do this only 7 times)
; rrf _KBcode,F ; use this instead for non-18F PIC's


!!! IMPORTANT !!! If you use an input other than INT2 (RB2) as your KBCLK line, be sure to change any INT2IE or INT2IF references in both the interrupt and KBmain routines to match your new assignment.


Whew!!! I think that pretty much covers it. Good Luck!

Kamikaze47
- 9th November 2005, 19:51
Ok cool. I spotted a couple of them already and changed them to suit a 16F84A, but i missed a couple. Thanks.

mytekcontrols
- 9th November 2005, 22:14
Kamikaze47,

Just out of curiousity, what are you doing that requires a full keyboard instead of something like a keypad?

Oh, and also just to let you know there are 2 keys that currently will not be decoded properly. The first is the PrntScrn/SysReq key which will put out a "*", and the other is the Pause/Break key which will mimic the NumLock key. I plan to do some more decoding for these, but simply haven't got to it yet. Any improvements you make and/or features you add, please post them here for all to see.

Thanks,
Michael

Kamikaze47
- 9th November 2005, 22:27
At the moment im going to be transmitting the decoded ascii characters over an RF link to another pic which will write them to an LCD screen. I've got the RF part working, so now just need to get the keyboard interface working.

Another project im thinking of doing with this is a device that goes inbetween your keyboard and your pc which will convert the keyboard to DVORAK. A friend of mine wants to have 2 keyboards on his PC - 1 QWERTY and 1 DVORAK, but the keyboard settings in windows are global so you cant have 2 different keyboard layouts.

Thanks for your help mytekcontrols. I'm sure this info will be usefull to a number of ppl on these forums.

mytekcontrols
- 10th November 2005, 01:11
Kamikaze47:

At the moment im going to be transmitting the decoded ascii characters over an RF link to another pic which will write them to an LCD screen. I've got the RF part working, so now just need to get the keyboard interface working.

Sounds like a very interesting project. Is this something you are doing for fun, or do you see it having commercial possiblities? If so, I hope it does well for you.

Well I put together all the pieces into one file and tested it out stand-alone. And then I pushed the compile button, while remembering that famous Clint Eastwood line "do you feel lucky?". Well I think you can guess the answer to that one. Of course there were a few errors :), but nothing too terrible.

Here is what was missing:

<img src="http://www.picbasic.co.uk/forum/images/icons/icon2.gif" align="absmiddle"> from the equates:


init var bit ' flag to use timeout test alternate return path
ktable var word ' translation table index


<img src="http://www.picbasic.co.uk/forum/images/icons/icon2.gif" align="absmiddle"> and from the PIC18F aliases:


INT2IP VAR INTCON3.7 ' INT2 external interrupt priority bit

(I screwed up on this one, and accidentally cut & pasted the wroung item)

Anyway once I fixed it, everything compiled and ran just fine. Total bytes required = 2626 (wow! pretty interesting result).

Download the complete and tested file below.

Kamikaze47
- 10th November 2005, 01:17
cool. thanks.

i havnt had time to get this running yet, i will work on it over the weekend and see how i go.

yea im basically just doing it for fun. but there are a couple of projects that i have done in the past that i think would have commercial potential, but i wouldnt know how to go about doing anything about them.

mytekcontrols
- 10th November 2005, 22:50
I tweaked the code in order to better mimic the actions of the keypad on a PC. Specifically I now have shifted functions in both NumLock and non-NumLock modes as outlined below:

NumLock Mode:
Shift-Up --- numbers are generated 0,1,2,3... (ascii $30 - $39)
Shift-Dn --- standard navigation INSERT, END, DOWN... (ascii $90 - $99)

non-NumLock Mode:
Shift-Up --- standard navigation INSERT, END, DOWN... (ascii $90 - $99)
Shift-Dn --- numbers are generated 0,1,2,3... (ascii $30 - $39)

Note: when in a number output mode, the delete key on the numpad = ".", else it generates the ascii $7F code for delete. Also please notice that all ascii assignments above $7F are of my choosing, and not a part of the standard ascii code set.

Code space requirements have gone up to 2666 with this new version.

srob
- 11th November 2005, 09:11
There is a pre-programmed PIC called PAK-VI available from milford instuments. I beleive they cost around £25. I've used them in the past and seems to work fine.

mytekcontrols
- 11th November 2005, 19:17
srob:

There is a pre-programmed PIC called PAK-VI available from milford instuments. I beleive they cost around £25.$29.95 USD

Yes I am familiar with this chip, and it certainly is an option. However when a person can go out and buy something like a PIC18F252 for about $8.00, put this ready-to-run piece of code into it, and still have 14K worth of programming space left, it really doesn't make much sense to do it the other way. The PAK-VI was really aimed more at a situation where a) you don't have an alternative method (i.e.; no keyboard code), or b) the existing processor is just not fast enough, or has enough memory to do this, and be able run your main program as well (i.e; BASIC Stamp).

Well I think I solved the "A" problem.

But don't get me wroung srob, it is always good to look at a problem from different angles and avail yourself of all the possible solutions.

Here is another update to the PS2 interface code. In this version I've added the ability to decode the Print Screen and Pause/Break keys. Also I've included an example of how to read the "alt" register and do something usefull. In the example a Ctrl+Alt+Delete key combo will do a Reset of your PIC. To really see this in action, initiate CapsLock, ScrollLock, or NumLock prior to the reset, and you should see the LED indicator turn off when the PIC re-initializes.

mytekcontrols
- 12th November 2005, 18:40
On the last PS2 Keyboard Interface update (V1.2) I failed to mention that I moved KBDAT from PortB.3 to PortB.4

This allowed me to use the hardware PWM aspect of PortB.3 for something else. As I had stated in an earlier post, the KBDAT I/O line can be freely moved anywhere of your choosing, by simply changing one equate, and without impacting anything else in the code. I simply took advantage of this fact.

Kamikaze47
- 13th November 2005, 18:33
Thanks for all the time ur putting into this mytekcontrols.

I was thinking about the problem of fitting this onto a 16F84 (which will be a problem), and i remembered that the 16F84 has 64 bytes of EEPROM data memory. I wonder if I could put some of the lookup tables on that memory in order to free up program memory.

mytekcontrols
- 14th November 2005, 01:04
Kamikaze47:

Thanks for all the time ur putting into this mytekcontrols

Actually I have a self-serving interest in doing this as well. I am designing a product that incorporates this code (along with a lot of other stuff), and I find it gives me incentive to improve it when someone else is in need of the same thing.

Kamikaze47:

I was thinking about the problem of fitting this onto a 16F84 (which will be a problem)

Just curious. Any reason you are persistant on using this particular processor? You really would be much better off using an 18F series chip like the PIC18F252 or PIC18F2525. Does it have something to do with not having a programmer for these?

Kamikaze47:

...i remembered that the 16F84 has 64 bytes of EEPROM data memory. I wonder if I could put some of the lookup tables on that memory in order to free up program memory

You certainly could. But it will only be of value if can you preload the eeprom with the DATA function in PBP, or have some other way to do it through your programmer.


Have fun with your project, and the best of luck squeezing it into your F84. <img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=615&stc=1&d=1131930010" align="absmiddle">

Kamikaze47
- 14th November 2005, 18:17
There are 2 reasons I would like to get it going on the 16F84. First its the most avaliable chip to me (can get them at my local electronics store), and secondly ive got a programmer for it. However, if need be i could modify the programmer to suit a different processor.

Anyway, ive been through the code to get familiar with it, and changed anything that would be different for a 16F84 (i dont think i missed anything). When I compile I get these warnings:

warning: unable to fit variable fsave in requested bank 16.
warning: unable to fit variable t1 in requested bank 16.
warning: unable to fit variable ssave in requested bank 16.
warning: unable to fit variable wsave in requested bank 16.
warning: unable to fit variable kbcnt in requested bank 16.
warning: unable to fit variable kbcode in requested bank 16.
warning: unable to fit variable kbindxi in requested bank 16.
warning: unable to fit variable kbindxo in requested bank 16.
warning: unable to fit variable kbbuf in requested bank 16.


*edit* Was just reading the F84 data sheet and looks like it labels the banks Bank0 and Bank1, so I changed the BankA's to Bank0's and the warnings disapeared... Got a bunch of new errors now, so will have to look at whats happening with them :)

mytekcontrols
- 15th November 2005, 04:14
Well if you are successful, please post your completed code, i'd love to see it :).

charudatt
- 30th March 2007, 08:25
any news on the code from Kamikaze47, seems to have disappeared.

regards

skimask
- 30th March 2007, 18:04
any news on the code from Kamikaze47, seems to have disappeared.

regards

Ya, like 1 1/2 years ago...

Pic_User
- 30th March 2007, 19:10
You are right. Last seen, June 2006.

You expect to see people disappear from threads labeled:
Interfacing AC power lines....
...transformerless DC supply...
How to design without opto-couplers ...
How to measure high voltage while standing in a bucket of water...

But not from a thread labeled, “AT/PS2 Keyboard - PIC Interface?” ?

Then again we have to consider his user name!
Kamikaze47 where are you??

-Adam-

skimask
- 30th March 2007, 20:22
You are right. Last seen, June 2006.

You expect to see people disappear from threads labeled:
Interfacing AC power lines....
...transformerless DC supply...
How to design without opto-couplers ...
How to measure high voltage while standing in a bucket of water...

But not from a thread labeled, “AT/PS2 Keyboard - PIC Interface?” ?

Then again we have to consider his user name!
Kamikaze47 where are you??

-Adam-

ROTFL :D
Good one...

Melanie
- 30th March 2007, 21:12
> How to measure high voltage while standing in a bucket of water...

charudatt
- 31st March 2007, 05:42
Instead of starting a new thread, i was just interested in continuing with the same topic.

I am looking for some idea on connecting a pic to the computer as a mouse in the PS/2 slot. Emulating a Mouse with a PIC.

Basic idea, I have two POT's connected to the PIC and one switch, I want cursor control in windows and the switch as the enter key , as in the mouse.

Any ideas, folks or headway.

regards

skimask
- 31st March 2007, 06:43
Instead of starting a new thread, i was just interested in continuing with the same topic.

I am looking for some idea on connecting a pic to the computer as a mouse in the PS/2 slot. Emulating a Mouse with a PIC.

Basic idea, I have two POT's connected to the PIC and one switch, I want cursor control in windows and the switch as the enter key , as in the mouse.

Any ideas, folks or headway.

regards

Tear an older, non-optical mouse apart, get rid of the slotted wheels, make a few cuts in the PCB, and trigger the X and Y wheel LEDs with the PIC instead of having them on 100% of the time with the mouse's circuitry. Worked for me, and once you get rid of the mouse case (mouse cage :) ), you've got a pretty small board to work with.

charudatt
- 31st March 2007, 19:38
Wow, you really gave me a good idea. Thank you.

Do you have any idea on how to input keycodes into the PC with the PIC.

regards

skimask
- 31st March 2007, 19:55
Wow, you really gave me a good idea. Thank you.

Do you have any idea on how to input keycodes into the PC with the PIC.

regards

Is the Search function here on the site broke again or what?

leisryan
- 6th April 2007, 01:42
this project is a milford chip 29.95$ buster!!! I've used it in several of my designs

http://www.electronic-engineering.ch/microchip/projects/keyboard/v1xx/keyboard_v1xx.html#faq_kbd_input

charudatt
- 8th April 2007, 18:15
HELLO GURU'S,

I AM TRYING TO SEND SOME FIXED CHARACTER FROM THE PIC TO THE PC VIA PS/2 WITHOUT ANY RESULT.

CAN SOMEONE PLEASE HELP !

BACKGROUND:
I HAVE JUST ADAPTED A CODE I FOUND ON THE NET FOR BS2 FOR MY PURPOSE. THE FILE IS ATTACHED TO THIS MAIL. ITS GOT SOME VERY GOOD DATA FOR HOW TO........ FOR THE PURPOSE.

THE ONLY DIFFERENCE IS THAT I HAVE DIRECTLY CONNECTED THE PORTPINS TO THE PC PS/2 CABLE SO AT A COUPLE OF PLACES I HAVE INVERTED THE SENDS.

MY CODE:

@ device PIC16F73 , hs_osc, wdt_off, pwrt_on, protect_oN
Include "MODEDEFS.BAS" ' Include Shiftin/out modes
'-----------------------------------------------------------------
Define Osc 8 ' We're using a 8 MHz oscillator
'-----------------------------------------------------------------
Adcon1 = 7 ' Set PORTA DIGITAL
OPTION_REG.7 = 1 ' DISABLE INTERNAL PULLUPS
Trisa = %00000000 ' SETS ALL PORTA PINS TO OUTPUT
Trisb = %00001100 ' ALL OUTPUT
Trisc = %00001011 ' 6 Pins - LCD and 2 Pins RF Module
'-----------------------------------------------------------------
SCLK VAR PORTB.1
SDATA VAR PORTB.0
LED VAR PORTC.5 ' LED
'-----------------------------------------------------------------
temp var BYTE 'Temp variabel
char var WORD 'Variabel containing the character
breakcode var WORD 'Variabel containing "Breakcode"
extcode var WORD 'Variabel containing "Extended charcode"
I VAR BYTE ' TEMP VARIABLE
' -----[ Initialization ]---------------------------------------------
'
'Set datpin and clkpin default to high (1)
HIGH SDATA ' low datpin
HIGH SCLK ' low clkpin

'Define breakcode
' s--DATA--PS (s=start, DATA=LSB First, P=parity, S=stop)
breakcode=%00000111111 '/F0H

'Define extcode
' s--DATA--PS (s=start, DATA=LSB First, P=parity, S=stop)
extcode=%00000011101 '/E0H

' -----[ Main Code ]--------------------------------------------------
'

PAUSE 4000 : LOW LED

start:

temp=0 : pause 1000
HIGH LED : GOSUB button00 : TEMP = 0 : PAUSE 500 : LOW LED : PAUSE 500
HIGH LED : GOSUB button01 : TEMP = 0 : PAUSE 500 : LOW LED : PAUSE 500
HIGH LED : GOSUB button02 : TEMP = 0 : PAUSE 500 : LOW LED : PAUSE 500
HIGH LED : GOSUB button03 : TEMP = 0 : PAUSE 500 : LOW LED : PAUSE 500
HIGH LED : GOSUB button04 : TEMP = 0 : PAUSE 500 : LOW LED : PAUSE 500
HIGH LED : GOSUB button05 : TEMP = 0 : PAUSE 500 : LOW LED : PAUSE 500

goto start

' -----[ Test Characters ]--------------------------------------------
' These are inverted
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%10110101110 '/SPACE
'char=%11100011110 '/a
'char=%11010010100 '/CR
'char=%11011001110 '/b
'char=%11100101110 '/t
'char=%10100101100 '/r
'char=%10011101110 '/d
'char=%10101111100 '/F1
'char=%11111000110 '/INS

button00:
'Assign char a character with startbit, parity and stopbit. OBS inverted !
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%11100011110 '/a
char=%00011100001 '/a
gosub sendchar
RETURN

button01:
'Assign char a character with startbit, parity and stopbit. OBS inverted !
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%11010010100 '/CR
char=%00101101011 '/CR
gosub sendchar
RETURN

button02:
'Assign char a character with startbit, parity and stopbit. OBS inverted !
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%11011001110 '/b
char=%00100110001 '/b
gosub sendchar
RETURN

button03:
'Assigne char a character with startbit, parity and stopbit. OBS inverted !
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%10110101110 '/SPACE
char=%01001010001 '/SPACE
gosub sendchar
goto start

button04:
'Assigne char a character with startbit, parity and stopbit. OBS inverted !
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%10101111100 '/F1
char=%01010000011 '/F1
gosub sendchar
RETURN

button05:
'Assigne char a character with startbit, parity and stopbit. OBS inverted !
' s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
'char=%11111000110 '/INS
char=%00000111001 '/INS
gosub sendextchar
RETURN

' -----[ Subroutines ]------------------------------------------------
'
sendchar
'Send character
shiftout SDATA,SCLK,1,[char\11] : pauseus 10
'Send breakcode + character
shiftout SDATA,SCLK,1,[breakcode\11] : pauseus 10
shiftout SDATA,SCLK,1,[char\11] : pauseus 10
return

sendextchar
'Send extcode + character SDATA
shiftout SDATA,SCLK,1,[extcode\11] : pauseus 10
shiftout SDATA,SCLK,1,[char\11] : pauseus 10
'Send extcode + breakcode + character
shiftout SDATA,SCLK,1,[extcode\11] : pauseus 10
shiftout SDATA,SCLK,1,[breakcode\11] : pauseus 10
shiftout SDATA,SCLK,1,[char\11] : pauseus 10
return

' -----[ End ]--------------------------------------------------------


ANY BETTER IDEA WOULD ALSO HELP.

REGARDS

keithdoxey
- 8th April 2007, 18:26
HELLO GURU'S,

I AM TRYING TO SEND SOME FIXED CHARACTER FROM THE PIC TO THE PC VIA PS/2 WITHOUT ANY RESULT.

CAN SOMEONE PLEASE HELP !

BACKGROUND:
I HAVE JUST ADAPTED A CODE I FOUND ON THE NET FOR BS2 FOR MY PURPOSE. THE FILE IS ATTACHED TO THIS MAIL. ITS GOT SOME VERY GOOD DATA FOR HOW TO........ FOR THE PURPOSE.

THE ONLY DIFFERENCE IS THAT I HAVE DIRECTLY CONNECTED THE PORTPINS TO THE PC PS/2 CABLE SO AT A COUPLE OF PLACES I HAVE INVERTED THE SENDS.

MY CODE:


WOW!!!!

Whilst a few of us here might might have slightly impaired hearing either due to geting older or working in nightclubs...or both... I dont believe we are totally deaf yet!!!

Please stop shouting or buy a keyboard that also has lower case letters on it as well !!!!

charudatt
- 8th April 2007, 18:41
I JUST FOUND THIS SITE VERY USEFUL (PDS CODE) AND THE CODE WORKED WITH ME. i COULD DECODE THE PS/2 KEYBOARD ATTACHED TO THE PIC ON THE LCD.

SORRY FOR PUTTING UP A PDS CODE. CAN ANYONE CONVERT IT FOR PBP. IT HAS A LOT OF ASM, WONDER WHY ?

http://users.picbasic.org/Howto/PC_keybrd/pc_keyboard.htm

REGARDS

charudatt
- 8th April 2007, 20:40
WOW!!!!

Whilst a few of us here might might have slightly impaired hearing either due to geting older or working in nightclubs...or both... I dont believe we are totally deaf yet!!!

Please stop shouting or buy a keyboard that also has lower case letters on it as well !!!!

I think i need to take your suggestion and shut my mouth about it.

regards

skimask
- 9th April 2007, 03:00
I JUST FOUND THIS SITE VERY USEFUL (PDS CODE) AND THE CODE WORKED WITH ME. i COULD DECODE THE PS/2 KEYBOARD ATTACHED TO THE PIC ON THE LCD. SORRY FOR PUTTING UP A PDS CODE. CAN ANYONE CONVERT IT FOR PBP. IT HAS A LOT OF ASM, WONDER WHY ? http://users.picbasic.org/Howto/PC_keybrd/pc_keyboard.htm
REGARDS

Why don't you try converting it over. Then if/when it doesn't work, we'll help you figure out why it doesn't work.

rookie11
- 18th February 2008, 03:53
Hi guys,

I was wondering if someone can help me out here on a simple task.
I've been learning a lot by reading about sending data to a keyboard's PS/2 port, but I am unable to send a simple letter and have it show up in notepad.exe on the host computer.

I know the following: data sent must have Start Bit = 0, Scancode (LSB First), Odd Parity, Stop Bit = 1.

Now, I don't care about keyboard initialization, because I will be booting up the PC with a normal keyboard attached, then swapping out the keyboard with my device.

All I want to do is send the letter 'q' ($15).

I am doing so by sending q (0+$51+0+1), then the release code (0+$0F+1+1), then q again (0+$51+0+1).

However, I am not getting anything on the host side of things.

Here is my code:






; PS2SendCode
;
; PIC16F648A
; _________________ _______________
; 1|RA2/AN2/VREF RA1/AN1|18
; 2|RA3/AN3/CMP1 RA0/AN0|17
; 3|RA4/TOCKI/CMP2 RA7/OSC1/CLKIN|16
; VPP ---> 4|RA5/MCLR/VPP RA6/OSC2/CLKOUT|15
; Gnd 5|Vss Vdd|14 +5
; 6|RB0/INT RB7/T1OSI/PGD|13 <--- PGD
; 7|RB1/RX/DT RB6/T1OSO/T1CKI/PGC|12 <--- PGC
; 8|RB2/TX/CK RB5|11 <--> PS2DATA
; PUSH BUTTON ---> 9|RB3/CCP1 RB4/PGM|10 <--- PS2CLK _|¯|_|¯|_|¯|_|¯|_
; ----------------------------------
;
;================================================= ==============================
; 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
;================================================= ==============================


@ errorlevel -223,-207,-306 ; Suppress useless messages
@ LIST P=PIC16F648A
@ __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF & _BODEN_OFF & _PWRTE_OFF & _LVP_OFF

;Using 4MHz oscillator
define OSC 4
;DEFINE SHIFT_PAUSEUS 43

PortB = 0 'Clear Port B
INTCON = 0 'Interrupts Off
CMCON = %00000111 'Disable Comparators
OPTION_REG.7 = 0 'Enable Port B Weak Pull-Ups

BitCnt VAR BYTE
KBTimeout VAR BYTE
ScanCode VAR Word
Parity Var BYTE
StartButton Var PortB.3
PS2Clk var PortB.4 '0
PS2Dat var PortB.5 '0
TRISB = %11111111 'Set PORTB pins direction to input

Start: pause 500

if startbutton = 0 then: goSUB StartSend

goto start

StartSend:
'SEND Q ($15 LSB FIRST)
Parity = 1 'Odd parity
scancode.0 = 0
Gosub sendbit 'send START BIT
scancode = %00010101 'send 'q'
For bitcnt = 1 To 8 'set for 8 data bits
Gosub sendbit 'send DATA BIT
If scancode.0 = 1 Then: parity = parity + 1
scancode = scancode >> 1 'shift out next bit
Next bitcnt
scancode.0 = parity.0
Gosub sendbit 'send PARITY BIT
scancode.0 = 1
Gosub sendbit 'send STOP BIT

'SEND RELEASE ($F0 LSB FIRST)
Parity = 1 'Odd parity
scancode.0 = 0
Gosub sendbit 'send START BIT
scancode = %11110000 'send '$F0'
For bitcnt = 1 To 8 'set for 8 data bits
Gosub sendbit 'send DATA BIT
If scancode.0 = 1 Then: parity = parity + 1
scancode = scancode >> 1 'shift out next bit
Next bitcnt
scancode.0 = parity.0
Gosub sendbit 'send PARITY BIT
scancode.0 = 1
Gosub sendbit 'send STOP BIT

'SEND Q ($15 LSB FIRST)
Parity = 1 'Odd parity
scancode.0 = 0
Gosub sendbit 'send START BIT
scancode = %00010101 'send 'q'
For bitcnt = 1 To 8 'set for 8 data bits
Gosub sendbit 'send DATA BIT
If scancode.0 = 1 Then: parity = parity + 1
scancode = scancode >> 1 'shift out next bit
Next bitcnt
scancode.0 = parity.0
Gosub sendbit 'send PARITY BIT
scancode.0 = 1
Gosub sendbit 'send STOP BIT

Return

SendBit:
'Looking for keyboard clock and data line to go high, then send data bit to it!
;If NOT(PS2Clk = 1 AND PS2Dat = 1) Then sendbit 'loop until clock line goes low
PS2Dat = scancode.0 'send data bit
return



Any advice appreciated.

sayzer
- 18th February 2008, 07:55
Take a look at post #6 at
http://www.picbasic.co.uk/forum/showthread.php?t=7962

Also, I am not sure about the way you control the Clock line in your code.

Kamikaze47
- 18th February 2008, 11:36
Yeah, your code seems to indicate that you are waiting for the clock line to do something?

Your device must generate the clock in this case.

sayzer
- 18th February 2008, 11:52
Ok, I misunderstood.

I now realized that you are SENDING data TO KB;
Not reading from it.

Sorry about that.

------------------------

Dave
- 18th February 2008, 12:17
rookie11, I don't think this code will ever work. Where are the ENDIF commands to terminate the IF statements?

Dave Purola,
N8NTA

skimask
- 19th February 2008, 04:26
rookie11, I don't think this code will ever work. Where are the ENDIF commands to terminate the IF statements?

Dave Purola,
N8NTA

One line If/Then statements....don't need an ENDIF....

If this=0 then gosub dothis : that=1 : goto something

...valid statement
If this is zero, then gosub dothis, set that to 1, then goto something.

But that colon following the THEN in the code a few posts back looks a bit strange to me...
And I know colons! :D

Dave
- 19th February 2008, 18:06
skimask , Look before you leap.... Look at where the colon lies........

Dave Purola.
N8NTA

skimask
- 19th February 2008, 19:43
skimask , Look before you leap.... Look at where the colon lies........

Dave Purola.
N8NTA

Well, I was talking about the code attached above. He has this line (along with another that's the same way):

If scancode.0 = 1 Then: parity = parity + 1
----------------------^

I don't know how that'll compile, if it will compile good and not cause an error, if it'll work as written, or what will happen. It just doesn't look right to me, that's all...

And I'm always keeping track of where my colon's lie... :)

Dave
- 20th February 2008, 11:38
skimask, The way I interpret a colon is to terminate a line of code and, allow the start of another command string to be placed on the same line. If this is the case then all of his IF/THEN statements should have and ending ENDIF command. I have not tried this as I never write code in this fashion. It is much to confusing and hard to follow the flow... Have you ever tried this format? If it works then GREAT...

Dave Purola,
N8NTA

skimask
- 20th February 2008, 14:00
It is much to confusing and hard to follow the flow... Have you ever tried this format? If it works then GREAT...

I guess I use whatever fits/works and takes up as few actual lines on the screen.
As far as being confusing, well, I usually don't write code for other folks (reference the High Colonic Master :) ), and if I wrote it for myself, then I'd better be able to follow it! And as long as a guy keeps a constant format...well, that should be all ya need...
But, I'm going to play with the If/Then colon format thing tonight when I get home and see what happens...

PJALM
- 21st February 2008, 15:49
Are you guys looking to emulate a PS/2 keyboard or get data from a PS/2 keyboard?

I have pure PBP code for both if you need it.

sayzer
- 21st February 2008, 16:10
Are you guys looking to emulate a PS/2 keyboard or get data from a PS/2 keyboard?

I have pure PBP code for both if you need it.

May I see the emulation code, then?
IF, of course, it is responding to the system commands ??


------------

skimask
- 21st February 2008, 18:16
May I see the emulation code, then?
IF, of course, it is responding to the system commands ??
------------

I second that commotion...no sense reinventing the wheel...
It's the responding back to the PC bit that gets me...

mpardinho
- 21st February 2008, 18:25
PJALM's

is possible upload the code?

i use http://www.picbasic.co.uk/forum/archive/index.php/t-2736.html but not work leds

many thanks

skimask
- 21st February 2008, 18:50
http://www.picbasic.co.uk/forum/archive/index.php/t-2736.html

Where have I seen that thread before? Guess I'll go to Post #1 and read through it again and try to figure it out. (i.e. endless loop)

sayzer
- 22nd February 2008, 09:07
I second that commotion...no sense reinventing the wheel...
It's the responding back to the PC bit that gets me...

Ski, I did not quite understand what you meant but,
PC (system) can terminate the communication while KB is sending data to it AND send system commands to it to have it do something; turn on/off status leds, resend last byte etc...

The thing is to detect this termination thingie during an active transmission.

This is what I meant.

skimask
- 22nd February 2008, 13:50
Ski, I did not quite understand what you meant but,
PC (system) can terminate the communication while KB is sending data to it AND send system commands to it to have it do something; turn on/off status leds, resend last byte etc...
The thing is to detect this termination thingie during an active transmission.
This is what I meant.

Ok, I was talking about the initial comm's to the keyboard when the PC powers up. It's been discussed in a couple of other threads somewhere.

gatlartech
- 17th April 2008, 05:52
Are you guys looking to emulate a PS/2 keyboard or get data from a PS/2 keyboard?

I have pure PBP code for both if you need it.


I am interested in code to emulate a PS/2 keyboard using a 16f88 interfacing to an embedded PC. Is it possible to view your PBP code?

charudatt
- 17th April 2008, 09:17
showed the carrot and now missing in action.

Where is the guy with the PBP code ?

ShoKre
- 4th May 2008, 15:47
i have to do 4x4 scan key to ps2 intf. with (one time) programmable keys, numeric part + some fonction key ie. P, A, X, Y...
but I'm not shure is it a lot of work in that system area,: tx ack, rx sys requests, init in PCstart, and others, if there is a way to put paralel with old kb board to do that portion, (if I dont hawe to switch betwen) then, sems to be easy ?

mister_e
- 4th May 2008, 18:26
PS2 emulation is harder than it seems. Maybe possible to fit a PIC in parallel of an existing controller, but i feel some potential bit collision one day or another.

I've done it with a single PIC, and frankly... enough time spent and wasted on it to hate it now :D

nomad
- 11th June 2008, 05:19
I've seen keyboard emulators in different gaming forums (mostly mame related), where it IS put in parallel with the keyboard.

anyways, I came across this function/macro/whatever for reading a ps/2 keyboard in great cow basic. says it's free and ok to copy sooo...




' PS/2 keyboard/mouse routines for Great Cow BASIC
' Copyright (C) 2006 Hugh Considine

' This library 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 2.1 of the License, or (at your option) any later version.

' This library 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
' Lesser General Public License for more details.

' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

'************************************************* *******************************
'IMPORTANT:
'THIS FILE IS ESSENTIAL FOR SOME OF THE COMMANDS IN GCBASIC. DO NOT ALTER THIS FILE
'UNLESS YOU KNOW WHAT YOU ARE DOING. CHANGING THIS FILE COULD RENDER SOME GCBASIC
'COMMANDS UNUSABLE!
'************************************************* *******************************

#define PS2Data SysTemp.0 'Set to data pin
#define PS2Clock SysTemp.0 'Set to clock pin

#startup InitPS2

'Initialise
sub InitPS2
DIR PS2Clock IN
DIR PS2Data IN
KeyShift = 0
MouseX = 0
MouseY = 0
end sub

'Return ASCII value of input key
function INKEY
'Initialise, and get key scan code
INKEY = 0
ScanCode = PS2ReadByte
if ScanCode = 0 then exit function

'2-byte key?
if ScanCode = 0xE0 then
do while INKEY = 0
INKEY = PS2ReadByte
loop
INKEY = INKEY OR 128
end if

'Shift/Capslock
if ScanCode = 0x12 or ScanCode = 0x59 then KeyShift = 1: exit function
if ScanCode = 0x58 then
if KeyShift = 2 then KeyShift = 0: exit function
KeyShift = 2
exit function
end if

'Translate scan code to ASCII

'Control Chars
if ScanCode = 0x5A then INKEY = 13 'Enter
if ScanCode = 0x66 then INKEY = 8 'Backspace
if ScanCode = 0x76 then INKEY = 27 'Esc
if ScanCode = 0x29 then INKEY = 32 'Space

'Arrows


'Numbers
if ScanCode = 0x45 then INKEY = 48
if ScanCode = 0x16 then INKEY = 49
if ScanCode = 0x1E then INKEY = 50
if ScanCode = 0x26 then INKEY = 51
if ScanCode = 0x25 then INKEY = 52
if ScanCode = 0x2E then INKEY = 53
if ScanCode = 0x36 then INKEY = 54
if ScanCode = 0x3D then INKEY = 55
if ScanCode = 0x3E then INKEY = 56
if ScanCode = 0x46 then INKEY = 57

'Letters
if ScanCode = 0x1C then INKEY = 65 'A
if ScanCode = 0x32 then INKEY = 66
if ScanCode = 0x21 then INKEY = 67 'C
if ScanCode = 0x23 then INKEY = 68
if ScanCode = 0x24 then INKEY = 69 'E
if ScanCode = 0x2B then INKEY = 70
if ScanCode = 0x34 then INKEY = 71 'G
if ScanCode = 0x33 then INKEY = 72
if ScanCode = 0x43 then INKEY = 73 'I
if ScanCode = 0x3B then INKEY = 74
if ScanCode = 0x42 then INKEY = 75 'K
if ScanCode = 0x4B then INKEY = 76
if ScanCode = 0x3A then INKEY = 77 'M
if ScanCode = 0x31 then INKEY = 78
if ScanCode = 0x44 then INKEY = 79 'O
if ScanCode = 0x4D then INKEY = 80
if ScanCode = 0x15 then INKEY = 81 'Q
if ScanCode = 0x2D then INKEY = 82
if ScanCode = 0x1B then INKEY = 83 'S
if ScanCode = 0x2C then INKEY = 84
if ScanCode = 0x3C then INKEY = 85 'U
if ScanCode = 0x2A then INKEY = 86
if ScanCode = 0x1D then INKEY = 87 'W
if ScanCode = 0x22 then INKEY = 88
if ScanCode = 0x35 then INKEY = 89 'Y
if ScanCode = 0x1A then INKEY = 90 'Z

if INKEY >= 65 and INKEY <= 90 and KeyShift = 0 then INKEY += 32

'Symbols
if ScanCode = 0x0E then INKEY = 96 '`
if ScanCode = 0x4E then INKEY = 45 '-
if ScanCode = 0x55 then INKEY = 61 '=
if ScanCode = 0x5D then INKEY = 92 '\
if ScanCode = 0x4c then INKEY = 59 ';
if ScanCode = 0x52 then INKEY = 39 ''
if ScanCode = 0x41 then INKEY = 44 ',
if ScanCode = 0x49 then INKEY = 46 '.
if ScanCode = 0x4A then INKEY = 47 '/

if KeyShift = 1 then KeyShift = 0

end function

function PS2ReadByte
PS2ReadByte = 0
if PS2Clock ON THEN exit function

'Start Bit
wait until PS2Clock OFF
if PS2Data ON then exit function
wait until PS2Clock ON

'8 data bits
For PS2Bit = 1 to 8
wait until PS2Clock OFF
set STATUS.C OFF
if PS2Data ON then set STATUS.C ON
ROTATE PS2ReadByte RIGHT
wait until PS2Clock ON
next

'Parity
wait until PS2Clock OFF
wait until PS2Clock ON

'End
wait until PS2Clock OFF
wait until PS2Clock ON
end function

sub PS2WriteByte (PS2Byte) #NR

'Take control
dir PS2Clock Out
set PS2Clock Off
wait 12 10us
dir PS2Data Out
set PS2Data Off
dir PS2Clock In

'Start Bit
wait until PS2Clock on
wait until PS2Clock off

PS2Parity = 0

'8 data bits
For PS2Bit = 1 to 8
if PS2Byte.0 Off then Set PS2Data off
if PS2Byte.0 On then Set PS2Data on: PS2Parity += 1
ROTATE PS2ReadByte RIGHT
wait until PS2Clock ON
wait until PS2Clock OFF
next

'Parity
if PS2Parity.0 off then Set PS2Data on
if PS2Parity.0 on then Set PS2Data off
wait until PS2Clock ON
wait until PS2Clock OFF

'Stop
set PS2Data On
wait until PS2Clock ON
wait until PS2Clock OFF

'Ack
Set PS2Data Off
wait until PS2Clock ON
dir PS2Data in

wait 100 10us

end sub


don't know if it'll do anyone any good, but....

sougata
- 21st July 2009, 18:34
Hi Michael,

I used your routine and it saved my life. Works like a breeze. Thanks for the great job and sharing it on this forum..

leisryan
- 22nd July 2009, 02:15
Hi Sougata:
Good day Bro, Can you share with me the routine?
Ryan

sougata
- 22nd July 2009, 06:37
Hi,

The code is right in this thread as a zip attachment. I used it along with DT's Interrupt system and it worked fine.

BobPigford
- 6th August 2009, 18:33
Hello!

I have implemented the wonderful code PS/2 keyboard code from mytekcontrols in my PIC18F4620. It will only work if I set
TOcntDLY CON to a value of 100 (originally set to 10 per mytekcontrols).

Furthermore, if I hit and hold any of the these three keys (Caps Lock, Num Lock, or Scroll Lock), there is no response from the keyboard LEDs and the program just hangs. These keys will work if I hit them VERY quickly (less than .1 second - just hit with a glancing blow).

Everything else works as it should (with the CON change above).

Is this a big timing issue for me? Settings when programming?

Reference:
PIC 18F4620
Internal OSC at 8Mhz
OSCCON = %01110010
BUT even with an external 20Mhz oscillator, same performance, still hangs!

I sense severe timing issues. I will welcome all suggestions with regard to fixing this code for me.

Thank you to all,
Bob Pigford
Newark, Delaware

sougata
- 6th August 2009, 20:24
Hi,

I used it on a 40MHz oscillator and did not have any issue. However the following may be considered:

1. Allow enough time (2 seconds or more is safe) before calling the PS2init routine. Your keyboard needs this to boot-up. Indicated by all three LEDs flashing and going off.

2. The characters are stored using interrupts but the interrupts are re-enabled only when parse it. This may cause the keyboards internal buffer to be overwhelmed.

BobPigford
- 7th August 2009, 18:59
Thank you sougata,


Hi,

I used it on a 40MHz oscillator and did not have any issue. However the following may be considered:

1. Allow enough time (2 seconds or more is safe) before calling the PS2init routine. Your keyboard needs this to boot-up. Indicated by all three LEDs flashing and going off.

2. The characters are stored using interrupts but the interrupts are re-enabled only when parse it. This may cause the keyboards internal buffer to be overwhelmed.

I did allow enough time for the keyboard to start. I see the LEDs flash, so I think that is not the issue.

I will follow you suggestion and look into the buffer situation. I will also order a 40mhz oscillator just to be sure.

I will report back on my progress.

Thank you again,
Bob Pigford
Newark, Delaware, USA

BobPigford
- 7th August 2009, 20:30
Thank you sougata,



I did allow enough time for the keyboard to start. I see the LEDs flash, so I think that is not the issue.

I will follow you suggestion and look into the buffer situation. I will also order a 40mhz oscillator just to be sure.

I will report back on my progress.

Thank you again,
Bob Pigford
Newark, Delaware, USA

I just isolated the issue! If I eliminate any output going TO the keyboard, everything works just fine! I disabled the "putkey" routine buy placing a "RETURN" immediately after the beginning of the routine.

Even with the internal oscillator at 8mhz, it all works very well (even with "TOcntDLY set back to 10)! I can live without seeing the LEDs on the keyboard for now. When my 40mhz oscillator arrives, it will try it again and report back.

Regards,
Bob

sougata
- 8th August 2009, 04:58
Hi,

Every PIC18 has got a x4 HSPLL oscillator mode. So you can use an external 10MHz crystal to effectively get 40 MHz Fosc. For internal 8MHz you need to configure osccon to enable HSPLL and get 8 x 4 = 32MHz from the internal oscillator.

BobPigford
- 9th August 2009, 16:10
Hi,

Every PIC18 has got a x4 HSPLL oscillator mode. So you can use an external 10MHz crystal to effectively get 40 MHz Fosc. For internal 8MHz you need to configure osccon to enable HSPLL and get 8 x 4 = 32MHz from the internal oscillator.

Thank you Sougata. I will give this a try and report back. And thank you for teaching me about HSPLL.
Regards,
Bob