PIC, Keyboard, and USART
|
|
Thread rating:  |
Abstract Dissonance - 23 Mar 2006 18:38 GMT I'm going to try to program a simple keyboard translator using the PIC2455 which has a built in EUSART. At this point I just want to get the keyboard codes into the pic and I just want to run this by you guys to make sure I'm on the right track.
1. Setup hardware. Basicaly just have to connect the Data and Clock lines to the EUSART pins on the pic 2. Enable the USART on the pic for Asynchronous mode and enable auto baud rate dection(to make it easy). 3. Read the RCREG in the interrupt and do whatever with it(like make an LED blink on certain codes).
Is that basicaly all I have to do? Do I need to use pullups or anything when connecting the lines or even use transistors to source/sink more current?
(I'm running the keyboard off a 5V supply that can source up to .5mA or so)
Any potential pitfalls with this?
Thanks, Jon
Jonathan Kirwan - 23 Mar 2006 18:41 GMT >I'm going to try to program a simple keyboard translator using the PIC2455 >which has a built in EUSART. At this point I just want to get the keyboard >codes into the pic and I just want to run this by you guys to make sure I'm >on the right track. Are you talking about a PC keyboard?
><snip> >Is that basicaly all I have to do? Do I need to use pullups or anything >when connecting the lines or even use transistors to source/sink more >current? Is this a PC keyboard?
>(I'm running the keyboard off a 5V supply that can source up to .5mA or so) 1/2 an mA???
>Any potential pitfalls with this? Could be. Is this a PC keyboard and are you really supplying it with at most half a milliamp??
Jon
Abstract Dissonance - 23 Mar 2006 21:51 GMT >>I'm going to try to program a simple keyboard translator using the PIC2455 >>which has a built in EUSART. At this point I just want to get the [quoted text clipped - 4 lines] > > Are you talking about a PC keyboard? Yes, Ofcourse... isn't it obvious? ;)
>><snip> >>Is that basicaly all I have to do? Do I need to use pullups or anything [quoted text clipped - 7 lines] > > 1/2 an mA??? Ofcourse not!!! .5A ;)
>>Any potential pitfalls with this? > > Could be. Is this a PC keyboard and are you really supplying it with > at most half a milliamp?? > > Jon Jon
Jonathan Kirwan - 23 Mar 2006 22:23 GMT I assume that you are talking about PC/AT keyboards here (or simply known as "AT keyboards.") I think the original PC keyboard was incompatible with the AT keyboard, but that all clones since that advent are now following the AT keyboard arrangement and I doubt you could even find a PC (non-AT) keyboard these days. Of course, I have long since forgotten, for sure. Do check on what I'm saying.
Regarding AT keyboards, there is a very detailed electrical spec of the hardware to be found in the IBM Technical Reference, Personal Computer AT set (4 volume set, which I will protect with my life!) That spec is the schematic itself, on page 17 of 22. They use '07 open-collector drivers tied to an RC filter, with 10k and 47pF.
+5 | / \ 10k / | |\ |
>----| >-----+--------------+---O (either connector pin 1 or 2) |/ | | | | --- | --- | | 47pF | | | --- | /// | | | <---------------------------'
That spells out the exact details of both pin 1 and pin 2. You should be able to note that the IBM PC can use either line is input or output. There is a reason for that design. If you intend to operate the keyboard correctly, you will need to mimic it.
You will _also_ need to fully understand how the keyboard is properly operated from the PC. It is discussed on pages 1-31 to 1-44 and all of chapter 4 of that Technical Reference I mentioned. But in particular there is the capability to observe aborts in transmission and to deal with conflicts in securing the interface from one side or the other.
I think that the technical details on the AT keyboard were fairly well considered by IBM before laying them out and the proper operation of the interface isn't entirely trivial, if you plan to get it right. There are very specific timing issues you need to be aware of. Have you searched the web for all this info? You should be aware of something called the "BAT" and the power up exchanges, graceful operation in the face of communication aborts, how to deal with moments when both you and the keyboard decide to talk to each other, etc.
Jon
Abstract Dissonance - 23 Mar 2006 22:48 GMT >I assume that you are talking about PC/AT keyboards here (or simply > known as "AT keyboards.") I think the original PC keyboard was [quoted text clipped - 8 lines] > That spec is the schematic itself, on page 17 of 22. They use '07 > open-collector drivers tied to an RC filter, with 10k and 47pF. Sheesh... that would be helpful to have. I wonder if one can download these online now?
> +5 > | [quoted text clipped - 20 lines] > output. There is a reason for that design. If you intend to operate > the keyboard correctly, you will need to mimic it. What is pin 1 and pin 2? The pins from the connectors? i.e., Data and Clock? Is that an inverter(buffer I guess)? (i.e. a bidirection link with a pullup and LP filter?)
> You will _also_ need to fully understand how the keyboard is properly > operated from the PC. It is discussed on pages 1-31 to 1-44 and all [quoted text clipped - 12 lines] > moments when both you and the keyboard decide to talk to each other, > etc. What I have found on the net is not completely technical but just what someone says works. Although they did point out certain issues they do not go into the details.
> Jon Thanks for the info. Its good to know there are technical specifications out there for this... now I just have to get my hands on it.
Thanks again, Jon
Jonathan Kirwan - 23 Mar 2006 22:56 GMT >>I assume that you are talking about PC/AT keyboards here (or simply >> known as "AT keyboards.") I think the original PC keyboard was [quoted text clipped - 11 lines] >Sheesh... that would be helpful to have. I wonder if one can download these >online now? Not that I'm aware of. I would suppose that IBM still holds the copyright to it -- it's not _that_ old, yet. I'd be happy to scan them in and post them up, if permission to do so could be found. It's irreplaceable. The set also includes _complete_ BIOS listings, as well. It's fairly complete, as I said.
>> +5 >> | [quoted text clipped - 24 lines] >Is that an inverter(buffer I guess)? (i.e. a bidirection link with a >pullup and LP filter?) As I understand the connector from the schematic (no, I haven't done keyboard experimentation on my own, so this isn't first hand), the 5-pin round DIN connector has pin 1 as clock and pin 2 as data. 3 is no-connect, 4 is GND, and 5 is the +5 supply.
>> You will _also_ need to fully understand how the keyboard is properly >> operated from the PC. It is discussed on pages 1-31 to 1-44 and all [quoted text clipped - 16 lines] >someone says works. Although they did point out certain issues they do not >go into the details. Bad news.
>Thanks for the info. Its good to know there are technical specifications >out there for this... now I just have to get my hands on it. Yes. It should be available somewhere. I've not looked around. But it should be out on the net, I'd hope.
Jon
Jonathan Kirwan - 23 Mar 2006 23:15 GMT On Thu, 23 Mar 2006 21:56:06 GMT, I wrote:
><snip> >>What is pin 1 and pin 2? The pins from the connectors? i.e., Data and Clock? [quoted text clipped - 6 lines] >no-connect, 4 is GND, and 5 is the +5 supply. ><snip> By the way, I'm not talking about USB keyboards. And I think the PS/2 keyboard connectors (which didn't exist when IBM was putting out that doc set) are 6-pin, not 5. But the mapping should be findable on the web. It's probably quite simple. (I have PS/2 to AT connector adapter plugs that I'm pretty sure just route lines.) It's slightly possible that the PS/2 keyboards have added to the specifications for the older DIN 5 connector types, adding more protocols.
The older DIN-5 connector only used 4 conductors. Two power and two signal. I have a weird USB-looking to PS/2-looking connector adapter that shows a mouse symbol embossed on the PS/2 end. No idea what it does, but it looks like it adapts something with a USB connector on it so that it plugs into a PS/2 mouse adapter hole on a IBM PC/AT system. So this makes me wonder about USB mice that can actually plug into a plug normally designed for PS/2 mice. If so, I'm baffled as it seems to suggest that USB might have been originally designed as an electrically compatible, but software incompatible, interface. If so, then it would be possible for a mouse with a USB connector on it to be plugged into a PS/2 mouse port and to auto-detect which it is talking with and switch protocols. So now I'm curious about that and interested in looking much more closely at the USB electrical spec.
Jon
Abstract Dissonance - 24 Mar 2006 00:43 GMT > On Thu, 23 Mar 2006 21:56:06 GMT, I wrote: > [quoted text clipped - 17 lines] > possible that the PS/2 keyboards have added to the specifications for > the older DIN 5 connector types, adding more protocols. yeah, the USB uses a HID protocol for keyboards.... something entirely different I guess. I've downloaded the specs but haven't been over them yet.
The 5 and 6 pin connectors are compatible but the order is different. The web site I have gave me the order but I'm not sure if it corresponds to what you have.
> The older DIN-5 connector only used 4 conductors. Two power and two > signal. I have a weird USB-looking to PS/2-looking connector adapter [quoted text clipped - 9 lines] > with and switch protocols. So now I'm curious about that and > interested in looking much more closely at the USB electrical spec. Could it be possible that there is some translation circuitry inside the connector? There is a difference in being that the USB uses a differential pair for data transmission so its not possible for a rewiring?
> Jon Thanks, Jon
Abstract Dissonance - 24 Mar 2006 00:48 GMT >>>I assume that you are talking about PC/AT keyboards here (or simply >>> known as "AT keyboards.") I think the original PC keyboard was [quoted text clipped - 18 lines] > irreplaceable. The set also includes _complete_ BIOS listings, as > well. It's fairly complete, as I said. Unfortunately that sucks... Its hard to find good documentation these days for some reason and I'm sure that the reference would be something that would come in handy.
>>> +5 >>> | [quoted text clipped - 30 lines] > 5-pin round DIN connector has pin 1 as clock and pin 2 as data. 3 is > no-connect, 4 is GND, and 5 is the +5 supply. hmm.. on the website I have looked at:
http://www.computer-engineering.org/ps2protocol/
there numbering is completely different ;/
oops... hehe... I am using the 6-pin DIN. So I guess it is what you are saying.
>>> You will _also_ need to fully understand how the keyboard is properly >>> operated from the PC. It is discussed on pages 1-31 to 1-44 and all [quoted text clipped - 19 lines] > > Bad news. Well, I guess I would have to look up the datasheet for the controller used(the 8051 or something like that?) to really know whats going on?
>>Thanks for the info. Its good to know there are technical specifications >>out there for this... now I just have to get my hands on it. > > Yes. It should be available somewhere. I've not looked around. But > it should be out on the net, I'd hope. Yeah... the problem nowdays is wading through all the crap sites... its on my nerves sometimes.
> Jon Thanks Again, Jon
David L. Jones - 23 Mar 2006 22:16 GMT > I'm going to try to program a simple keyboard translator using the PIC2455 > which has a built in EUSART. At this point I just want to get the keyboard [quoted text clipped - 5 lines] > 2. Enable the USART on the pic for Asynchronous mode and enable auto baud > rate dection(to make it easy). No. You will need *synchronous* slave mode which uses the external clock from the keyboard.
> 3. Read the RCREG in the interrupt and do whatever with it(like make an LED > blink on certain codes). > > Is that basicaly all I have to do? Do I need to use pullups or anything > when connecting the lines or even use transistors to source/sink more > current? Yes, use pullup resistors.
> (I'm running the keyboard off a 5V supply that can source up to .5mA or so) The keyboard takes a lot more than 0.5mA! Dave :)
Abstract Dissonance - 23 Mar 2006 22:50 GMT >> I'm going to try to program a simple keyboard translator using the >> PIC2455 [quoted text clipped - 12 lines] > No. You will need *synchronous* slave mode which uses the external > clock from the keyboard. Why is this? Wouldn't the auto baud rate detect and interrupts work? I will look at it though and see... I'm not to familiar with the different methods. I was thinking that each time the clock pulsed it would trigger an interrupt and you could read the data off the data line and store it... or something like that.
>> 3. Read the RCREG in the interrupt and do whatever with it(like make an >> LED [quoted text clipped - 10 lines] > > The keyboard takes a lot more than 0.5mA! Sure ;)
> Dave :) Thanks, Jon
David L. Jones - 24 Mar 2006 01:21 GMT > >> I'm going to try to program a simple keyboard translator using the > >> PIC2455 [quoted text clipped - 18 lines] > and you could read the data off the data line and store it... or something > like that. For starters, you said you were going to hook the CLK line from the keyboard up to the TX pin of the USART. If you use asynchronous mode then the TX pin will be an output, you can't feed a clock input into an output pin!
You have 3 options: 1) Connect Keyboard DATA to RX and Keyboard CLK to TX *and* use synchronous slave mode. This should work although I have never done it myself. The USART baud rate will use external CLK from the keyboard. You *cannot* connect the CLK line and use asynchronous mode, that's not the way asynchronous works.
2) Connect Keyboard DATA to RX only and forget the CLK line. Use asynchronous mode and let the USART module detect the baud rate. This may not work, the keyboard is not a set frequency and may not have a defined start bit (I can't remember exactly).
3) Connect the Keyboard DATA and CLK lines to normal I/O pins on the PIC. You can then interrupt off the CLK line falling edge (if you want to use interrupts). Then just decode in software. When the CLK line goes low you call a function which reads all your bits and constructs the byte. No need for a USART module. I've done this and it works fine. Plenty of example code around too. Only if your processor is taxed with other tasks at the same time will you have to use a USART for this. Dave :)
Abstract Dissonance - 25 Mar 2006 22:59 GMT >> >> I'm going to try to program a simple keyboard translator using the >> >> PIC2455 [quoted text clipped - 30 lines] > then the TX pin will be an output, you can't feed a clock input into an > output pin! I was thinking that the autobaud rate stuff needed a line to sense the "clock" on... I didn't know it could sense it directly from the data ;/ (like what if you sense all low's... how can it sense?)
> You have 3 options: > 1) Connect Keyboard DATA to RX and Keyboard CLK to TX *and* use > synchronous slave mode. This should work although I have never done it > myself. The USART baud rate will use external CLK from the keyboard. > You *cannot* connect the CLK line and use asynchronous mode, that's not > the way asynchronous works. I thought asynchronous was basicaly for bidirectionality? In the specs it says that asynch mode is the only one that supports full-duplex or something like that and also is the only one that will use the autobaud rate dectionion.
> 2) Connect Keyboard DATA to RX only and forget the CLK line. Use > asynchronous mode and let the USART module detect the baud rate. This > may not work, the keyboard is not a set frequency and may not have a > defined start bit (I can't remember exactly). What is a "defined start bit"? The serial data consists of a start bit, 8 data bits, 1 parity, and 1 stop bit.
> 3) Connect the Keyboard DATA and CLK lines to normal I/O pins on the > PIC. You can then interrupt off the CLK line falling edge (if you want [quoted text clipped - 5 lines] > Only if your processor is taxed with other tasks at the same time will > you have to use a USART for this. This is the more intuitive way but I feel I'm doing more than I have to(which isn't a bad think necessarily but...). I figure that since I have the USART I might as well take advantage of it. I might try both the asynch and synch methods and see what happens.
> Dave :) Thanks, Jon
Jonathan Kirwan - 23 Mar 2006 23:00 GMT >> I'm going to try to program a simple keyboard translator using the PIC2455 >> which has a built in EUSART. At this point I just want to get the keyboard [quoted text clipped - 9 lines] >clock from the keyboard. ><snip> Actually, the clock line should also be able to be driven by the non-keyboard end of things, as well. The other end is responsible for it's own clock driving action. These are bi-directional lines supporting bi-directional communication and there is a negotiating protocol that should be supported.
Jon
Abstract Dissonance - 24 Mar 2006 00:52 GMT >>> I'm going to try to program a simple keyboard translator using the >>> PIC2455 [quoted text clipped - 22 lines] > > Jon yeah... There is a "master" and "slave". When the master pulls the clock low the slave waits for a transmission and if it was in the process of tranmitting it will have to resend later(and buffer its data)... or something like that. At this point I just want to make sure I can read what the keyboard has to say... I have no logic analyzer to "see" whats going on and I don't like guessing. I'm not to worried about sending commands to the keyboard yet but would just like to know its "working".
Jon
Anthony Fremont - 24 Mar 2006 01:23 GMT > I'm going to try to program a simple keyboard translator using the PIC2455 > which has a built in EUSART. At this point I just want to get the keyboard [quoted text clipped - 11 lines] > when connecting the lines or even use transistors to source/sink more > current? A PC keyboard doesn't spit out async serial data, they are synchronous (allot like I2C as I recall). There are some other things you need to know as well, like that the keyboard can talk three different protocols. That means you have to send it some data to initialize it unless you want the default output.
I did this a few years ago on a 16F84, it was the first thing I did with a PIC. It read data from a keyboard, partially translated the scancodes and sent it out a serial port. Here is some code that should get you started on the road to communicating with the hateful things. ;-)
The cheesy serial code I glommed from the internet along with some other bits here and there. Now when I bit-bang serial, I use timer interrupts to clock things in and out. This code is a real mess, but it should work using a 4MHz clock. You'll certainly need to make some changes to get it running on an 18F.
;----------------------------------------------------------------------- ---------------------- ; HEADER: ;----------------------------------------------------------------------- ---------------------- LIST P=16f84 RADIX DEC INCLUDE "p16f84.inc" __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
;----------------------------------------------------------------------- ---------------------- ; EQUATES: ;----------------------------------------------------------------------- ---------------------- RS equ 0 ;LCD's pin 4 should be connected to PORTB.0 RW equ 1 ;LCD's pin 5 should be connected to PORTB.1 EN equ 2 ;LCD's pin 6 should be connected to PORTB.2
KBCLK equ 1 ;Keyboard's clock pin connected to PORTA.1 KBDATA equ 2 ;Keyboard's data pin connected to PORTA.2
TEMP0 equ 0x0C ;Four general purpose registers TEMP1 equ 0x0D TEMP2 equ 0x0E TEMP3 equ 0x0F
#define SERIAL_OUT PORTA, 0
; DELAY_TIME should be (ClockSpeed/4/SerialSpeed-14)/3 ; 4MHz 9600 baud would be (4000000/4/9600-14)/3 = 30 ; 4MHz 2400=134 4800=65 9600=30 19200=13 38400=4 57600=1
; 10Mhz 4800=169 DELAY_TIME equ D'30'
Scancode equ 0x10 ;Added by mike AsciiValue equ 0x11 KBFlags equ 0x12 ;Keyboard Flags byte SHIFT equ 0 ;Shift key down flag ALT equ 1 ;Alt key down flag CTRL equ 2 ;Ctrl key down flag
cblock 0x13 ; variables serialDelayCount serialCount serialData endc
;----------------------------------------------------------------------- ---------------------- ; START: ;----------------------------------------------------------------------- ---------------------- org 0x000 goto Start org 0x004 goto Start
Start bsf STATUS, RP0 ;Switch to Bank 1 movlw b'00000110' ;Define I/O on Port A (KBCLK and KBDATA input) movwf TRISA & 0x07F movlw b'00000000' ;Define I/O on Port B (LCD Display output) movwf TRISB & 0x07F bcf STATUS, RP0 ;Back to Bank 0 clrf PORTA ;Initialize PORTA clrf PORTB ;Initialize PORTB clrf KBFlags ;Turn off all flags for keyboard call KBCLK_Low ;Put keyboard on hold right away call serialInit ;get ready for serial stuff
movlw 0x01 ;Wait a while for keyboard to init call Delay movlw 0x01 ;Wait a while for keyboard to init call Delay movlw 0x01 ;Wait a while for keyboard to init call Delay
call Read_KB ;trash the keyboards post code
Main call Read_KB ;Get a scancode byte into W movwf Scancode ;Save it
; goto PrintIt ;Skip over checks
movf Scancode, w xorlw 0x12 ;Was it left shift key down btfsc STATUS, Z goto SKeyDown ;Special key down
movf Scancode, w xorlw 0x59 ;Was it right shift key down btfsc STATUS, Z goto SKeyDown ;Shift key down
movf Scancode, w xorlw 0xF0 ;Was it a break code prefix - F0 btfsc STATUS, Z goto DoBreak ;Yes, so process it
movf Scancode, w ;Restore W xorlw 0xE0 ;Was it a different break code prefix - E0 btfsc STATUS, Z goto Skipit ;Yes, so skip it
movf Scancode, w ;Restore W xorlw 0xE1 ;Was it a different break code prefix - E1 btfsc STATUS, Z goto Skipit ;Yes, so skip it
goto PrintIt ;It passed the checks for printability
SKeyDown bsf KBFlags, SHIFT ;Set the shifted flag goto Main
SKeyUp bcf KBFlags, SHIFT ;Un-Set the shifted flag goto Main
DoBreak call Read_KB ;Get a scancode into w movwf Scancode ;Save it
movf Scancode, w xorlw 0x12 ;Was it left shift key up btfsc STATUS, Z goto SKeyUp ;Shift key up
movf Scancode, w xorlw 0x59 ;Was it right shift key up btfsc STATUS, Z goto SKeyUp ;Shift key up
goto Main ;Get next scancode ; ;Skip the break code and the next keyboard byte after receiving break code ; Skipit call Read_KB ;get a scancode byte goto Main ; and throw it away
PrintIt movf Scancode, w ;Load the scancode and call Translate ; get ascii value into W movwf AsciiValue ;Save it
; movf AsciiValue, W ;Refresh W call serialTransmit ;Send the keystroke
goto Main ;Read/Display again ;----------------------------------------------------------------------- ------- ; ; Translate - Convert scancode in W to ASCII returned in W ; ;----------------------------------------------------------------------- ------- Translate andlw 0x7f ;Maintain sanity (less than 128) movwf TEMP3 ;Save truncated scancode temporarily btfsc KBFlags, SHIFT ;Are we shifted or not goto kb_shifted ;Yes, use shifted table ;No, use primary table MOVLW HIGH XLAT_Tbl + 1 ;Move the High Byte of the first table ;location into W MOVWF PCLATH ;and then into PCLATH MOVLW XLAT_Tbl + 1 ;Load W with the address of the first ; piece of data in Table2 ADDWF TEMP3,w ;Calculate the offset address and BTFSC STATUS, C ; see if it overflows INCF PCLATH,f ;If so, increment PCLATH and CALL XLAT_Tbl ;Jump to the data table entry (translating scan code) return kb_shifted MOVLW HIGH XLAT_Shift + 1 ;Move the High Byte of the first table ;location into W MOVWF PCLATH ;and then into PCLATH MOVLW XLAT_Shift + 1 ;Load W with the address of the first ; piece of data in Table2 ADDWF TEMP3,w ;Calculate the offset address and BTFSC STATUS, C ; see if it overflows INCF PCLATH,f ;If so, increment PCLATH and CALL XLAT_Shift ;Jump to the data table entry (translating scan code) return
;--------------------------------------------------- ; ; Read the keyboard and return scancode in W ; ;--------------------------------------------------- Read_KB call KBCLK_Norm ;clear to send now call PS2_Get movwf TEMP3 ;Save scancode byte read call KBCLK_Low ;turn off the KB movf TEMP3, w ;Return with scancode in W return
;--------------------------------------------------- ; ; KCLK_Low - Pull the keyboard clock line low ; ;--------------------------------------------------- KBCLK_Low bsf STATUS, RP0 ;Make KBCLK an Output bcf TRISA & 0x07F, KBCLK bcf STATUS, RP0 bcf PORTA, KBCLK ;Pull it low ; movlw 0xFE ;Wait at least 100 microseconds. ; call Delay return
;----------------------------------------------------------------------- ; ; KCLK_Norm - Return keyboard clock line back to normal operation ; ;----------------------------------------------------------------------- KBCLK_Norm bsf STATUS, RP0 ;Select Bank 1. bsf TRISA & 0x07F, KBCLK ;Make PORTA.1 Input Again bcf STATUS, RP0 ;Back to Bank 0. return
Delay movwf TEMP0 ;Efficient, imprecise delay routine addlw 1 btfsc STATUS, Z incfsz TEMP0, f goto $ - 3 return
PS2_Get call PS2_Get1 ;Get/ignore the start bit movlw d'8' ;Load Counter movwf TEMP0 PS2_Get0 rrf TEMP1, f call PS2_Get1 ;Read a bit from the keyboard/mouse iorwf TEMP1, f ;TEMP1.7 = bit read from device iorlw b'01111111' andwf TEMP1, f decfsz TEMP0, f ;Read 8 data bits yet? goto PS2_Get0 ; No. Get another bit. call PS2_Get1 ; Yes. Get/ignore parity bit. call PS2_Get1 ;Get/ignore stop bit movf TEMP1, w ;Put result in w. return ;Done--return.
PS2_Get1 btfss PORTA, KBCLK ;Make sure clock is high. goto $ - 1 btfsc PORTA, KBCLK ;Read data on falling edge goto $ - 1 btfss PORTA, KBDATA ;Read data. retlw b'00000000' ; w.7 = bit read. retlw b'10000000' ; w.7 = bit read. ;----------------------------------------------------------------------- - ; ; Serial Port Stuff ; ;----------------------------------------------------------------------- - serialDelayThird movlw DELAY_TIME/3 movwf serialDelayCount ; only count 1/3 goto serialDelayLoop ; use routine below serialDelay movlw DELAY_TIME movwf serialDelayCount ; Count down from DELAY_TIME nop ; Helps with high speed serialDelayLoop decfsz serialDelayCount, F ; Countdown goto serialDelayLoop ; keep counting return ; done ;_______________________________________________________________________ _
serialInit bsf STATUS, RP0 ; Select Bank 1 ; bsf SERIAL_IN ; Setup input bcf SERIAL_OUT ; Setup output bcf STATUS, RP0 ; Select Bank 0 bsf SERIAL_OUT return
;_______________________________________________________________________ _
serialTransmit movwf serialData ; save the outgoing byte movlw D'10' movwf serialCount ; set the bit count clrc ; prep for start bit serialTransmitLoop bsf SERIAL_OUT ; assume send low skpc ; if sending 0 bcf SERIAL_OUT ; send high call serialDelay ; delay setc ; prep for stop bit rrf serialData, F ; roll serialIn bits decfsz serialCount, F ; if not complete goto serialTransmitLoop ; loop back for more return ; all done ;
;serialReceive ; btfss SERIAL_IN ; Check for Start bit ; retlw 0 ; not receiving now ; movlw D'9' ; movwf serialCount ; gonna read 9 bits ; call serialDelayThird ; skip third a bit ;serialReceiveLoop ; clrc ; assume clear carry ; btfss SERIAL_IN ; if receiving 0 ; setc ; set carry ; rrf serialData, F ; roll serialData bits ; call serialDelay ; delay ; nop ; keep timing w/ transmit ; decfsz serialCount, F ; if not complete ; goto serialReceiveLoop ; loop back for more ; movfw serialData ; return the data ; return
org 0x1FF XLAT_Tbl movwf PCL retlw 0xFF ;00 retlw 0xFF ;01 retlw 0xFF ;02 retlw 0xFF ;03 retlw 0xFF ;04 retlw 0xFF ;05 retlw 0xFF ;06 retlw 0xFF ;07 retlw 0xFF ;08 retlw 0xFF ;09 retlw 0xFF ;0A retlw 0xFF ;0B retlw 0xFF ;0C retlw 0xFF ;0D retlw 0xFF ;0E retlw 0xFF ;0F retlw 0xFF ;10 retlw 0xFF ;11 retlw 0xFF ;12 retlw 0xFF ;13 retlw 0xFF ;14 retlw 'q' ;15 retlw '1' ;16 retlw 0xFF ;17 retlw 0xFF ;18 retlw 0xFF ;19 retlw 'z' ;1A retlw 's' ;1B retlw 'a' ;1C retlw 'w' ;1D retlw '2' ;1E retlw 0xFF ;1F retlw 0xFF ;20 retlw 'c' ;21 retlw 'x' ;22 retlw 'd' ;23 retlw 'e' ;24 retlw '4' ;25 retlw '3' ;26 retlw 0xFF ;27 retlw 0xFF ;28 retlw ' ' ;29 retlw 'v' ;2A retlw 'f' ;2B retlw 't' ;2C retlw 'r' ;2D retlw '5' ;2E retlw 0xFF ;2F retlw 0xFF ;30 retlw 'n' ;31 retlw 'b' ;32 retlw 'h' ;33 retlw 'g' ;34 retlw 'y' ;35 retlw '6' ;36 retlw 0xFF ;37 retlw 0xFF ;38 retlw 0xFF ;39 retlw 'm' ;3A retlw 'j' ;3B retlw 'u' ;3C retlw '7' ;3D retlw '8' ;3E retlw 0xFF ;3F retlw 0xFF ;40 retlw ',' ;41 retlw 'k' ;42 retlw 'i' ;43 retlw 'o' ;44 retlw '0' ;45 retlw '9' ;46 retlw 0xFF ;47 retlw 0xFF ;48 retlw '.' ;49 retlw '/' ;4A retlw 'l' ;4B retlw ';' ;4C retlw 'p' ;4D retlw '-' ;4E retlw 0xFF ;4F retlw 0xFF ;50 retlw 0xFF ;51 retlw '\'' ;52 retlw 0xFF ;53 retlw '[' ;54 retlw '=' ;55 retlw 0xFF ;56 retlw 0xFF ;57 retlw 0xFF ;58 retlw 0xFF ;59 retlw 0x0D ;5A retlw ']' ;5B retlw 0xFF ;5C retlw '\\' ;5D retlw 0xFF ;5E retlw 0xFF ;5F retlw 0xFF ;60 retlw 0xFF ;61 retlw 0xFF ;62 retlw 0xFF ;63 retlw 0xFF ;64 retlw 0xFF ;65 retlw 0xFF ;66 retlw 0xFF ;67 retlw 0xFF ;68 retlw 0xFF ;69 retlw 0xFF ;6A retlw 0xFF ;6B retlw 0xFF ;6C retlw 0xFF ;6D retlw 0xFF ;6E retlw 0xFF ;6F retlw 0xFF ;70 retlw 0xFF ;71 retlw 0xFF ;72 retlw 0xFF ;73 retlw 0xFF ;74 retlw 0xFF ;75 retlw 0xFF ;76 retlw 0xFF ;77 retlw 0xFF ;78 retlw 0xFF ;79 retlw 0xFF ;7A retlw 0xFF ;7B retlw 0xFF ;7C retlw 0xFF ;7D retlw 0xFF ;7E retlw 0xFF ;7F
org 0x2FF XLAT_Shift movwf PCL retlw 0xFF ;00 retlw 0xFF ;01 retlw 0xFF ;02 retlw 0xFF ;03 retlw 0xFF ;04 retlw 0xFF ;05 retlw 0xFF ;06 retlw 0xFF ;07 retlw 0xFF ;08 retlw 0xFF ;09 retlw 0xFF ;0A retlw 0xFF ;0B retlw 0xFF ;0C retlw 0xFF ;0D retlw 0xFF ;0E retlw 0xFF ;0F retlw 0xFF ;10 retlw 0xFF ;11 retlw 0xFF ;12 retlw 0xFF ;13 retlw 0xFF ;14 retlw 'Q' ;15 retlw '!' ;16 retlw 0xFF ;17 retlw 0xFF ;18 retlw 0xFF ;19 retlw 'Z' ;1A retlw 'S' ;1B retlw 'A' ;1C retlw 'W' ;1D retlw '@' ;1E retlw 0xFF ;1F retlw 0xFF ;20 retlw 'C' ;21 retlw 'X' ;22 retlw 'D' ;23 retlw 'E' ;24 retlw '$' ;25 retlw '#' ;26 retlw 0xFF ;27 retlw 0xFF ;28 retlw ' ' ;29 retlw 'V' ;2A retlw 'F' ;2B retlw 'T' ;2C retlw 'R' ;2D retlw '%' ;2E retlw 0xFF ;2F retlw 0xFF ;30 retlw 'N' ;31 retlw 'B' ;32 retlw 'H' ;33 retlw 'G' ;34 retlw 'Y' ;35 retlw '^' ;36 retlw 0xFF ;37 retlw 0xFF ;38 retlw 0xFF ;39 retlw 'M' ;3A retlw 'J' ;3B retlw 'U' ;3C retlw '&' ;3D retlw '*' ;3E retlw 0xFF ;3F retlw 0xFF ;40 retlw '<' ;41 retlw 'K' ;42 retlw 'I' ;43 retlw 'O' ;44 retlw ')' ;45 retlw '(' ;46 retlw 0xFF ;47 retlw 0xFF ;48 retlw '>' ;49 retlw '?' ;4A retlw 'L' ;4B retlw ':' ;4C retlw 'P' ;4D retlw '_' ;4E retlw 0xFF ;4F retlw 0xFF ;50 retlw 0xFF ;51 retlw '\"' ;52 retlw 0xFF ;53 retlw '{' ;54 retlw '+' ;55 retlw 0xFF ;56 retlw 0xFF ;57 retlw 0xFF ;58 retlw 0xFF ;59 retlw 0x0D ;5A retlw '}' ;5B retlw 0xFF ;5C retlw '|' ;5D retlw 0xFF ;5E retlw 0xFF ;5F retlw 0xFF ;60 retlw 0xFF ;61 retlw 0xFF ;62 retlw 0xFF ;63 retlw 0xFF ;64 retlw 0xFF ;65 retlw 0xFF ;66 retlw 0xFF ;67 retlw 0xFF ;68 retlw 0xFF ;69 retlw 0xFF ;6A retlw 0xFF ;6B retlw 0xFF ;6C retlw 0xFF ;6D retlw 0xFF ;6E retlw 0xFF ;6F retlw 0xFF ;70 retlw 0xFF ;71 retlw 0xFF ;72 retlw 0xFF ;73 retlw 0xFF ;74 retlw 0xFF ;75 retlw 0xFF ;76 retlw 0xFF ;77 retlw 0xFF ;78 retlw 0xFF ;79 retlw 0xFF ;7A retlw 0xFF ;7B retlw 0xFF ;7C retlw 0xFF ;7D retlw 0xFF ;7E retlw 0xFF ;7F end
Abstract Dissonance - 25 Mar 2006 23:03 GMT >> I'm going to try to program a simple keyboard translator using the > PIC2455 [quoted text clipped - 24 lines] > That means you have to send it some data to initialize it unless you > want the default output. I didn't know this. I can't seem to find good info on it ;/ Most are just what some people have done to get it to work but nothing technical and specific ;/
> I did this a few years ago on a 16F84, it was the first thing I did with > a PIC. It read data from a keyboard, partially translated the scancodes [quoted text clipped - 6 lines] > work using a 4MHz clock. You'll certainly need to make some changes to > get it running on an 18F. yeah. I was thinking I could setup a timed interrupt but what I have read says that the keyboard's clock can be anywhere from 10khz to 20khz so this doesn't help(and you would need to sample twice as fast or something). I like the edge triggered interrupt method since its pretty straight forward.
Seems to me the USART handles everything for me directly though and it would be nice to take advantage of it if its not to difficult.
I'll look at your code and see what I can get from it. I just need to start playing around I guess.
Thanks,
Jon
> ;----------------------------------------------------------------------- > ---------------------- [quoted text clipped - 616 lines] > retlw 0xFF ;7F > end Jan Wagner - 26 Mar 2006 12:04 GMT > I'm going to try to program a simple keyboard translator using the PIC2455 > which has a built in EUSART. At this point I just want to get the keyboard [quoted text clipped - 13 lines] > > (I'm running the keyboard off a 5V supply that can source up to .5mA or so) Apart from the "writing bugs" others already commented on, doing this with UART could be a real nightmare. Ok, 9600 baud and 8 databit, 1 odd parity, 1 start and 1 stop bit, and separate clock input, it is basically easy (if your microcontroller supports that many bits!! 11 of them). But then there is also the bidirectional communication needed especially if you want to configure the keyboard to something sensible by sending commands to it. Basically you'd have to switch off the UART and put the pins into output mode for the handshakes etc, then switch back to UART again to receive or transmit. For both receive /and/ transmit, you'd have to use the clock provided by the keyboard, i.e. synchronous UART. It's a real mess.
You can find some valuable background info at http://www.beyondlogic.org/keyboard/keybrd.htm#1
If you only want to receive, and your uC does support full 11 bits UART ("Enhanced USART" sounds like it might, but then maybe that's just marketing bull...) then this should be very easy to do.
Just add the pull-up resistors, data line to UART RX, clock input not strictly necessary - until you want to transmit.
regards, - Jan
Abstract Dissonance - 28 Mar 2006 05:12 GMT >> I'm going to try to program a simple keyboard translator using the >> PIC2455 which has a built in EUSART. At this point I just want to get [quoted text clipped - 25 lines] > transmit. For both receive /and/ transmit, you'd have to use the clock > provided by the keyboard, i.e. synchronous UART. It's a real mess. yeah... after looking at slave mode I saw this. Difference between master and slave is who supplies the clock.
I was thinking that all I would have to do is switch between master and slave mode for tranmission and reception. Not sure if this would work though or not... I'd still have to setup the clock speed properly for tranmission but I figure that it shouldn't be to hard to do cause they are two disjoint parts. The main problem is when worrying about collisions.
> You can find some valuable background info at > http://www.beyondlogic.org/keyboard/keybrd.htm#1 Yeah, I'm still trying to read up on all this stuff. Its a good site but trying to make some sense of the datasheet for the pic. It gives different methods to do the same thing and I'm confused on which is right.
> If you only want to receive, and your uC does support full 11 bits UART > ("Enhanced USART" sounds like it might, but then maybe that's just > marketing bull...) then this should be very easy to do. Well, I'm not sure. It says 9-bits but not sure if that includes the start and stop bit ;/
> Just add the pull-up resistors, data line to UART RX, clock input not > strictly necessary - until you want to transmit. ? Is that for asynch mode? I'd need to use the clock in slave mode for the getting data? (since I don't know its data rate). I could use asynch mode and auto detect the clock but I'm not sure how reliable this is ;/ and I think there has to be a calibration test or something and I have no idea how to get that done.
> regards, > - Jan Thanks, Jon
Jan Wagner - 28 Mar 2006 20:40 GMT > I was thinking that all I would have to do is switch between master and > slave mode for tranmission and reception. Basically yes, but, with the additional protocol thingy in between to tell the keyboard that it should start clocking data in and not out.
> Not sure if this would work > though or not... I'd still have to setup the clock speed properly for > tranmission but I figure that it shouldn't be to hard to do cause they are > two disjoint parts. The main problem is when worrying about collisions. The way I've seen this and used the keyboard is that the keyboard actually is always master and provides the clock i.e. tells the PC when it can start sending a command byte. But I'm not an AT keyboard specifications guru, maybe the specs provide for a little-known slave mode also.
>> You can find some valuable background info at >> http://www.beyondlogic.org/keyboard/keybrd.htm#1 [quoted text clipped - 9 lines] > Well, I'm not sure. It says 9-bits but not sure if that includes the start > and stop bit ;/ I had a quick glance at the PIC18F2455 datasheet (I like to spot PIC flaws ;-)), and searched the PDF for "parity". Not many search results.
In section 20.2 EUSART Asynchronous Mode the datasheet says that "Parity is not supported by the hardware but can be implemented in software and stored as the 9th data bit.". So the USART might not be that "Enhanced" after all if, it lacks such basic features as parity bit. But it's up to you to check the PIC18 family users guide etc in more depth to see if this is actually the full truth or not (considering it is a PIC, it'd be hardly surprising if the parity feature was really missing ;-)
Anyway, from that one datasheet sentence I'd guess the Enhanced USART does only start + stop bit and 7..9 bits of data. So if you want to /receive/, enable 9 bit mode, and ignore the 9th bit (since at only 9600 baud the chance for errors must be really small :)) For transmitting something, do the parity calculation in software.
>> Just add the pull-up resistors, data line to UART RX, clock input not >> strictly necessary - until you want to transmit. [quoted text clipped - 4 lines] > think there has to be a calibration test or something and I have no idea how > to get that done. Yup, asynch, no need for the external clock when receiving because basically the keyboard is supposed to be sending at 9600baud (IIRC).
Your PIC UART will (or, /should/ ;-) sync up at the start bit automatically, provided you have set the UART to a fixed 9600 baud and don't use any kind of unreliable "automatic baud rate detection" features.
With UART set to 9600 baud the actual data rate or delay between bytes is irrelevant, as long as bit rate of one individual byte is those 9600 baud - and the PC keyboard takes care of that already.
regards, - Jan
Abstract Dissonance - 29 Mar 2006 06:45 GMT >> I was thinking that all I would have to do is switch between master and >> slave mode for tranmission and reception. [quoted text clipped - 11 lines] > start sending a command byte. But I'm not an AT keyboard specifications > guru, maybe the specs provide for a little-known slave mode also. I'm not sure. My foggy recollection from a few web sites is that when transmitting to the keyboard you gotta hold the clock line low for a certain amount of time and the keyboard will know then that you are going to transmit something and then will wait. I'm not sure if I'm even close but thats what I remember at this point.
>>> You can find some valuable background info at >> [quoted text clipped - 28 lines] > chance for errors must be really small :)) For transmitting something, do > the parity calculation in software. yeah, it does start, stop and 8 to 9 data bits but treats the 9th bit as data and not something special like parity. I'm not sure if I need to do parity at this point since I wouldn't even know how to request tranmission of data. I'm still trying to figure out how to use the USART for my pic. The docs are pretty technical but I get a little lost in know exactly what to do. They give the info on all the bits and a small description but hell if I know how to use them properly(like in what order and stuff). They do give some example code and I think I'm making it harder than what it is.
I figure that I just have to flip a few bits to set the right mode and put some code on an interrupt to handle when I recieve the data and hopefully it should work.
>>> Just add the pull-up resistors, data line to UART RX, clock input not >>> strictly necessary - until you want to transmit. [quoted text clipped - 7 lines] > Yup, asynch, no need for the external clock when receiving because > basically the keyboard is supposed to be sending at 9600baud (IIRC). what if the clock is a bit off? Not sure if I want to do asynch yet since I have the clock availiable. Seems like one less problem to worry about if something doesn't work.
> Your PIC UART will (or, /should/ ;-) sync up at the start bit > automatically, provided you have set the UART to a fixed 9600 baud and [quoted text clipped - 3 lines] > irrelevant, as long as bit rate of one individual byte is those 9600 > baud - and the PC keyboard takes care of that already. and if its not? ;/ lol. Damn I wish I would have kept all those keyboards that I ruined by spilling crap on them... Could have looked the what chips they were using and got the data sheet on them ;/
> regards, > - Jan Thanks again, Jon
techie_alison - 29 Mar 2006 19:24 GMT > what if the clock is a bit off? Not sure if I want to do asynch yet since I > have the clock availiable. Seems like one less problem to worry about if > something doesn't work.
> and if its not? ;/ lol. Damn I wish I would have kept all those keyboards > that I ruined by spilling crap on them... Could have looked the what chips [quoted text clipped - 5 lines] > Thanks again, > Jon Hello,
I've done this with both PS2 mice and keyboards on a 16F628. Using the internal pull-ups and standard I/O ports. Never used the UART as the PS2 standard is weird basically, someone at IBM was having a really bad day.
What I would suggest is that you start from the bottom up by trial and error. you WILL need to implement procedures for both MASTER>SLAVE and SLAVE>MASTER communication. Mice for example won't report until you tell them too, some keyboard's too. Also, kit from different manufacturers works at slightly different speeds. The way I did it was to poll for input and then time out after a set period. Doing it this way also allows you to build in the ability to hot-swap the slave devices by using some conditional branches and alike. Asking a mouse it's status will tell you if it's been hot-swapped or not.
Detecting errors with PS2 packets is also a nightmare too, as parity detection is only right half of the time... In the end I used parity and also checked for wayyyy-out values, then asking the slave to retransmit them.
PS2 as a standard is possibly as dreadful as USB. The other alternative would be to use a decoder chip instead so that plain values are presented to the MCU and you don't have to worry about PS2 at all.
These are the documents I referred to at the time; http://www.computer-engineering.org/ps2protocol/ A digital dual trace scope may also be handy. Basically implement from the ground up bit by bit.
:) Hope that helps a bit :)
Aly
ps. a snippet for you from some code laying about, don't ask me about it, long time since the picture was in my head.
; -------------------------------------- ; READ A SINGLE BYTE FROM THE PS2 DEVICE ; -------------------------------------- ;on exit, byte read contained in ps2_byte_
PS2_RECEIVE_BYTE CLRF ps2_byte_ ;reset our variable MOVLW 8 ;8 bits to be read MOVWF ps2_bits_remaining_ CLRF ps2_calculated_parity_ ;parity will be stored in here Wait_for_start_bit: COMF PORTB, W ; wait till CLOCK and DATA are high ANDLW b'11000000' BTFSS STATUS,Z GOTO Wait_for_start_bit CALL PS2_WAIT_FOR_CLOCK_LOW BTFSC ps2_control_flags_, PS2_TIMEOUT_ GOTO Ps2_read_byte_timeout Read_start_bit: MOVF PORTB, W ANDLW b'01000000' MOVWF ps2_start_bit_ CALL PS2_WAIT_FOR_CLOCK_HIGH BTFSS ps2_start_bit_, 0x06 GOTO Start_bit_good
Start_bit_bad: GOTO Wait_for_start_bit Start_bit_good: Read_data_bit: CALL PS2_WAIT_FOR_CLOCK_LOW ;have to wait for it to go high again
BCF STATUS, C ;we don't want an accident for what we're going to do now RRF ps2_byte_, F ;rotate one to the right BTFSS PORTB, PS2_DATA_PORTB_ GOTO Read_data_bit_is_0 Read_data_bit_is_1: BSF ps2_byte_, 0x07 INCF ps2_calculated_parity_, F Read_data_bit_is_0: CALL PS2_WAIT_FOR_CLOCK_HIGH
;if we skipped to here, then it remains a 0 ;time to get the next bit now
;we now need to check if we've read 8 bits ;if not, then we do this again DECFSZ ps2_bits_remaining_, F GOTO Read_data_bit
;ok, so we're here, that's our byte read ;now it's the parity bit about to come CALL PS2_WAIT_FOR_CLOCK_LOW
MOVF PORTB, W ANDLW b'01000000' MOVWF ps2_parity_bit_
;our parity bit is now on data ;we're going to discard it!!
;now to wait for the end bit CALL PS2_WAIT_FOR_CLOCK_HIGH
CALL PS2_WAIT_FOR_CLOCK_LOW
MOVF PORTB, W ANDLW b'01000000' MOVWF ps2_stop_bit_ ;discard it, no action!!
;our byte is now sitting in ps2_byte_ Ps2_read_byte_timeout: RETURN
|
|
|