Shop Learn
trouble with synchronous serial receive — Parallax Forums

trouble with synchronous serial receive

kwagnerkwagner Posts: 20
edited 2021-09-08 11:45 in Propeller 2

Hi all,

I'm attempting to make a basic keyboard code reader for the PS/2 click, and running into an issue. The protocol looks like this: https://www.researchgate.net/figure/PS-2-protocol-involved-in-the-keyboard-to-computer-communication_fig7_220848551 A clock signal is usually high, and pulses low when data is available. 11 bits are used: 1 start, 8 data, 1 parity, 1 stop. At first I was manually checking the pin values but I was told about the synchronous serial receive smart pin option which sounded like a more intelligent way to do things.

From the propeller manual, "When a word is received, IN is raised and the data can then be read via RDPIN/RQPIN." My problem is, IN is always 1, if I'm understanding how to read it correctly.

A snipped of code here:

CON
   PIN_KEY = 32 ' keyboard data input
   PIN_CLK = 33 ' keyboard clock input
   _CLKFREQ = 250_000_000
VAR
   hitKey ' what key is currently hit   
PUB Start()|startTime,tempk,deltaTime
   PinFloat(PIN_KEY)
   PinFloat(PIN_CLK)
   WRPin(%0000_1001_000_0000000000000_00_11101_0,PIN_KEY) ' synchronous serial receive on PIN_KEY, with inverted clock on PIN_KEY+1
   WXPin(%11010,PIN_KEY) ' read 11 bits of data coincident with clock edge
   hitKey := 0
   startTime := getms()
   repeat
      repeat
         ' use synchronous serial receive to grab bits off the pin, if available.
         if PinRead(PIN_KEY) == 1 ' there's data waiting
            tempk := RDPin(PIN_KEY)
            if tempk <> 0
               hitKey := 1
         deltaTime := getms()-startTime
      while deltaTime < 50
      'do something with hitKey here

My understanding is PinRead is used as a flag in smart pin mode to say that data has been received. However, it appears to always be 1, whether or not I'm typing on the keyboard. I tried inverting the clock signal, but that didn't have an effect. Is there something else I'm missing (not setting something right, some other command, etc), or is my understanding of this smart pin method incorrect?

Comments

  • roglohrogloh Posts: 3,556

    Do you have a pullup resistor fitted on your clock and data pins? Most PS/2 devices are open collector output IIRC.

  • jmgjmg Posts: 14,813
    edited 2021-09-08 02:18

    @kwagner said:
    Hi all,

    I'm attempting to make a basic keyboard code reader for the PS/2 click, and running into an issue. The protocol looks like this: https://www.researchgate.net/figure/PS-2-protocol-involved-in-the-keyboard-to-computer-communication_fig7_220848551 A clock signal is usually high, and pulses low when data is available. 11 bits are used: 1 start, 8 data, 1 parity, 1 stop. At first I was manually checking the pin values but I was told about the synchronous serial receive smart pin option which sounded like a more intelligent way to do things.

    Better PS/2 info is here :
    http://www.hardwarebook.info/AT_Keyboard/Mouse_protocol
    PS/2 is a bit more complicated than a simple synchronous serial, as both the clock and data pins are bidirectional, and I guess you want to support LED controls ?
    LEDs are often used for power-up and user check the keyboard is connected and alive.

  • JonnyMacJonnyMac Posts: 7,708
    edited 2021-09-08 03:19

    @kwagner If you use three back-ticks (on ~ key) above and below your code, you don't have to add the dots (which make it difficult for those wanting to copy-and-paste your snippets)

      This will be formatted like code
    

    There is a P1 object in the standard Propeller library called keyboard.spin that Chip wrote many years ago -- it might be a place to start.

  • Cluso99Cluso99 Posts: 17,955

    Here is a 1-pin keyboard driver. I use the PS2 Keyboard as a serial receive only. Note the baud has to be determined as PS2 keyboards vary the speed - probably a cheap RC oscillator version keyboard chip.
    https://forums.parallax.com/discussion/120422/debug-to-tv-using-1-pintv-option-1-pinkbd-minimal-footprint-screen-buf-overl

  • Thanks all. I'll try to address one at a time:

    @rogloh said:
    Do you have a pullup resistor fitted on your clock and data pins? Most PS/2 devices are open collector output IIRC.

    @jmg said:
    Better PS/2 info is here :
    http://www.hardwarebook.info/AT_Keyboard/Mouse_protocol
    PS/2 is a bit more complicated than a simple synchronous serial, as both the clock and data pins are bidirectional, and I guess you want to support LED controls ?
    LEDs are often used for power-up and user check the keyboard is connected and alive.

    For this specific project, I only care about receipt. I don't need to set LEDs and I can assume the keyboard is present. Hopefully that makes things easier.

    @JonnyMac said:
    @kwagner If you use three back-ticks (on ~ key) above and below your code, you don't have to add the dots (which make it difficult for those wanting to copy-and-paste your snippets)

      This will be formatted like code
    

    Thanks! I tried a few different methods, but couldn't get it right. When I used the "code" option from the dropdown above the comment box, it only used two back-ticks and put the cursor in the middle of them. I couldn't figure out the right way to format it from that, so I did the blockquote instead (which of course trimmed whitespace). Fixed now.

    There is a P1 object in the standard Propeller library called keyboard.spin that Chip wrote many years ago -- it might be a place to start.

    Thanks! I'll take a look.

    @Cluso99 said:
    Here is a 1-pin keyboard driver. I use the PS2 Keyboard as a serial receive only. Note the baud has to be determined as PS2 keyboards vary the speed - probably a cheap RC oscillator version keyboard chip.
    https://forums.parallax.com/discussion/120422/debug-to-tv-using-1-pintv-option-1-pinkbd-minimal-footprint-screen-buf-overl

    I'll check this out as well. All the keyboards should be the same for this project, so I would hope they all use the same speed. I wasn't sure if a given keyboard had a consistent baudrate since the clock only goes out when a key is pressed/released. I suppose it would be possible to do like how the old DOS games calibrated joysticks on startup, have the user press a key and sample the clock speed from that.

  • So Chip's code looks like what I was doing originally (which makes sense as it's for a P1):

    receive                 test    _cpin,#$20      wc      'wait indefinitely for initial clock low
                            waitpne cmask,cmask
    receive_ack
                            mov     x,#11                   'ready 11 bits
    receive_bit             call    #wait_c0                'wait until clock low
                            movs    napshr,#16              'pause ~16us
                            call    #nap
    _d3                     test    dmask,ina       wc      'input data bit
                            rcr     data,#1
                            mov     wcond,c1                'wait until clock high
                            call    #wait
                            djnz    x,#receive_bit          'another bit?
    
                            shr     data,#22                'align byte
                            test    data,#$1FF      wc      'if parity error, reset keyboard
            if_nc           jmp     #reset
    rand                    and     data,#$FF               'isolate byte
    

    Since that seemed to work before, I'll stick with that logic to continue with my project, and revisit it later when I understand smart pins more :)

  • Cluso99Cluso99 Posts: 17,955

    @kwagner said:
    Thanks all. I'll try to address one at a time:

    @rogloh said:
    Do you have a pullup resistor fitted on your clock and data pins? Most PS/2 devices are open collector output IIRC.

    @jmg said:
    Better PS/2 info is here :
    http://www.hardwarebook.info/AT_Keyboard/Mouse_protocol
    PS/2 is a bit more complicated than a simple synchronous serial, as both the clock and data pins are bidirectional, and I guess you want to support LED controls ?
    LEDs are often used for power-up and user check the keyboard is connected and alive.

    For this specific project, I only care about receipt. I don't need to set LEDs and I can assume the keyboard is present. Hopefully that makes things easier.

    @JonnyMac said:
    @kwagner If you use three back-ticks (on ~ key) above and below your code, you don't have to add the dots (which make it difficult for those wanting to copy-and-paste your snippets)

      This will be formatted like code
    

    Thanks! I tried a few different methods, but couldn't get it right. When I used the "code" option from the dropdown above the comment box, it only used two back-ticks and put the cursor in the middle of them. I couldn't figure out the right way to format it from that, so I did the blockquote instead (which of course trimmed whitespace). Fixed now.

    There is a P1 object in the standard Propeller library called keyboard.spin that Chip wrote many years ago -- it might be a place to start.

    Thanks! I'll take a look.

    @Cluso99 said:
    Here is a 1-pin keyboard driver. I use the PS2 Keyboard as a serial receive only. Note the baud has to be determined as PS2 keyboards vary the speed - probably a cheap RC oscillator version keyboard chip.
    https://forums.parallax.com/discussion/120422/debug-to-tv-using-1-pintv-option-1-pinkbd-minimal-footprint-screen-buf-overl

    I'll check this out as well. All the keyboards should be the same for this project, so I would hope they all use the same speed. I wasn't sure if a given keyboard had a consistent baudrate since the clock only goes out when a key is pressed/released. I suppose it would be possible to do like how the old DOS games calibrated joysticks on startup, have the user press a key and sample the clock speed from that.

    I tested a number of keyboards, some were just PS2 and some were USB with PS2 support. It was necessary to have 10K pull-ups (5V, not sure if 3V3 will work) and a series resistor (value from standard P1 schematic - 180R???).
    The speed varied considerably between keyboards - way more than the spec said!!!
    I could tune easily by sending a space char from the keyboard. Standard async serial works IIRC.
    Checkout the code. It’s quite simple.

  • @Cluso99 said:
    I tested a number of keyboards, some were just PS2 and some were USB with PS2 support. It was necessary to have 10K pull-ups (5V, not sure if 3V3 will work) and a series resistor (value from standard P1 schematic - 180R???).
    The speed varied considerably between keyboards - way more than the spec said!!!
    I could tune easily by sending a space char from the keyboard. Standard async serial works IIRC.
    Checkout the code. It’s quite simple.

    Interesting. I haven't added any resistors yet, maybe it's the click or the keyboard is just lucky in that regard?

    Here's the code that I have working. I gave it its own cog and it seems to behave itself:

    PRI HandleKeys()|tempk,k,odd,tempp
        k1 := 0
        k2 := 0
        k3 := 0
        repeat
            ' first make sure the clock is high so we don't start in the middle of a press or release
            repeat while PinRead(PIN_CLK) == 0
            ' now we check for a low, which signals the start of a key
            repeat while PinRead(PIN_CLK) == 1
            ' process the next bits
            odd := 0
            repeat k from 1 to 10
                repeat while PinRead(PIN_CLK) == 0 ' last bit
                repeat while PinRead(PIN_CLK) == 1 ' clock up, key bit changing
                tempp := PinRead(PIN_KEY)
                if k < 10
                    odd += tempp
                tempk := (tempk>>1)+(tempp<<9)
            repeat while PinRead(PIN_CLK) == 0 ' bleed off the stop bit
            ' make sure the odd parity is good. otherwise, reject
            if (odd == 1) or (odd == 3) or (odd == 5) or (odd == 7) or (odd == 9)
                ' save it in the k's
                k3 := k2
                k2 := k1
                k1 := tempk & %11111111 ' we don't care about parity and stop bits
    
  • Cluso99Cluso99 Posts: 17,955

    You need the 10K pullups !!!

  • If I'm reading this schematic right, the PS/2 click has 1K pullups built in:
    https://download.mikroe.com/documents/add-on-boards/click/ps2/ps2-click-manual-v100.pdf
    Is that sufficient?

  • roglohrogloh Posts: 3,556
    edited 2021-09-13 12:27

    @kwagner said:
    If I'm reading this schematic right, the PS/2 click has 1K pullups built in:
    https://download.mikroe.com/documents/add-on-boards/click/ps2/ps2-click-manual-v100.pdf
    Is that sufficient?

    That should suffice.

    It would be nice if there was a bit more resistance to not load the P2 with 5V so much, but I think the protection diodes would take it. My own rule of thumb from the P1 days is not to put more than 0.5mA through them so I'd choose around 2k2 but 1k should still work.

  • evanhevanh Posts: 11,685
    edited 2021-09-13 17:06

    [doh! posted in wrong topic]

Sign In or Register to comment.