Connect with us

PIC, Keyboard, and USART

Discussion in 'Electronic Basics' started by Abstract Dissonance, Mar 23, 2006.

  1. 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
     
  2. Are you talking about a PC keyboard?
    Is this a PC keyboard?
    1/2 an mA???
    Could be. Is this a PC keyboard and are you really supplying it with
    at most half a milliamp??

    Jon
     
  3. Yes, Ofcourse... isn't it obvious? ;)
    Ofcourse not!!! .5A ;)
    Jon
     
  4. No. You will need *synchronous* slave mode which uses the external
    clock from the keyboard.
    Yes, use pullup resistors.
    The keyboard takes a lot more than 0.5mA!

    Dave :)
     
  5. 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
    /
    |
    |\ |
    |/ | |
    | |
    --- |
    --- |
    | 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
     

  6. Sheesh... that would be helpful to have. I wonder if one can download these
    online now?


    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?)

    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.

    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
     
  7. 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.


    Sure ;)
    Thanks,
    Jon
     
  8. 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.
    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.
    Bad news.
    Yes. It should be available somewhere. I've not looked around. But
    it should be out on the net, I'd hope.

    Jon
     
  9. 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
     
  10. 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
     
  11. 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.
    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?
    Thanks,
    Jon
     
  12. 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.
    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.
    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?

    Yeah... the problem nowdays is wading through all the crap sites... its on
    my nerves sometimes.
    Thanks Again,
    Jon
     
  13. 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
     
  14. 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 :)
     
  15. 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
     
  16. 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?)
    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.
    What is a "defined start bit"? The serial data consists of a start bit, 8
    data bits, 1 parity, and 1 stop bit.
    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.
    Thanks,
    Jon
     
  17. 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 ;/
    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
     
  18. Jan Wagner

    Jan Wagner Guest

    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
     
  19. 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.
    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.
    Well, I'm not sure. It says 9-bits but not sure if that includes the start
    and stop bit ;/
    ? 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.
    Thanks,
    Jon
     
  20. Jan Wagner

    Jan Wagner Guest

    Basically yes, but, with the additional protocol thingy in between to
    tell the keyboard that it should start clocking data in and not out.
    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.
    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.
    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
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-