Shop OBEX P1 Docs P2 Docs Learn Events
Smartpin mode sync serial pin issues — Parallax Forums

Smartpin mode sync serial pin issues

I'm dabbling with smartpins for the first time. I have a SPI connection between a Raspberry PI 4 and the P2. The PI is the Controller, P2 is device (I prefer that over master/slave).

I can see the clock and data lines working. I generate random data on the CODI-line, and both CLK and CODI look great on the scope.

So I pulled up the smart pin documentation by Jon Titus and learned about the sync serial pin mode. I use his example to sample from the clock-pin with the following pasm method:

con
  CLK = 10
  CODI = 11

pri spi_test()
org
  ' output on pins 56-59
  mov dirb, ##$0f00_0000

.smartpin
  dirl #CODI                    'Reset receiver Smart Pin
  wrpin sync_rx_mode, #CODI     'Set sync receiver mode
  wxpin #%1_00111, #CODI                'Set receiver to sample on B-
                                      ' input edge
  dirh #CODI                          'Enable Smart-Pin sync receiver
.test_loop
  testp #CODI  wc                       'Wait in loop IN flag = set
  nop
if_nc jmp #.test_loop                   'If no C flag, repeat testing
  rqpin rcvd_data, #CODI        'Put 32-bit data (see text) in
  mov outb, rcvd_data           'Send 8 bit data to LEDs
  jmp #.test_loop               'Continue to rcv and display
                                ' data

sync_rx_mode    long  %0000_0101_000_0000000000000_01_11101_0
rcvd_data   long  $00
end

According to the documentation the BBBB selects normal logic, -1 from the pin number - and CLK is pin 10.

Now when I look at the CODI-line with my scope, the signal is severely dampened.

Any idea what's going on here?

Also: currently clock is not touched in any way, as I figured that it would by default be an input, and that's that. But is this correct, or do I need some sort of smartpin-input-mode for CLK as well?

Comments

  • JonnyMacJonnyMac Posts: 8,918
    edited 2021-09-07 21:27

    Given that Parallax compilers have smart pin constants built in (that I think are available in FlexSpin, too), I think it wise to use them instead of manually declaring them. Here's a little Spin demo (easy to translate to PASM) that works, and shows how to deal with MSBFIRST and LSBFIRST values.

    Note that I used a couple F-F jumper wires to connect my output pins to my input pins so that I didn't have to so anything unnecessary with the sync rx setup.

      m := P_SYNC_RX                                                ' spi rx mode
      m |= ((SCKI-CIDO) & %111) << 24                               ' add SCK offset (B pin)
      x := %0_00000 | (8-1)                                         ' sample ahead of b pin rise, 8 bits
      pinstart(CIDO, m, x, 0)                                       ' configure smart pin
      pinfloat(CIDO)                                                ' reset/disable until used
      pinfloat(SCKI)                                                ' make SCK an input
    
  • evanhevanh Posts: 15,171
    edited 2021-09-07 22:10

    @deets said:
    ...
    So I pulled up the smart pin documentation by Jon Titus and learned about the sync serial pin mode. I use his example to sample from the clock-pin with the following pasm method:

    ...
    sync_rx_mode    long  %0000_0101_000_0000000000000_01_11101_0
    rcvd_data long  $00
    end
    

    According to the documentation the BBBB selects normal logic, -1 from the pin number - and CLK is pin 10.

    Okay, your "sync_rx_mode" is selecting pin - 3 for inputB. So that won't work. And %TT=%01 is also wrong. That sets the output driven when the smartpin is on.

    This exact listing has a familiar ring to it. Someone else not long ago did exactly the same. Maybe best not to follow Mr Titus's examples. Avoid hand-coding the bit patterns when there is prebuilt ones ready to go. Less errors then.
    Here's the correct pin mode: sync_rx_mode long P_MINUS1_B | P_SYNC_RX

    Also: currently clock is not touched in any way, as I figured that it would by default be an input, and that's that. But is this correct, or do I need some sort of smartpin-input-mode for CLK as well?

    In your case the rx data pin was driving its output, having a fight with the device at the other end.

    Inputs are always operating. Although they can be diverted and also changed type. Default input type is plain logic level; can be changed via the %P..P bit-field. %AAAA and %BBBB is your diverters, they select which inputs to look at.

  • @JonnyMac @evanh Thank you for the suggestion to use the constants. This did in fact do the trick. I'm in general a fan of doing this, however you have to start somewhere, so using examples you think can be trusted as stepping stone is to be expected I believe.

    I will comment on the document and reference this thread.

    Next step: streaming the expected 768 into RAM or LUT.

  • evanhevanh Posts: 15,171

    Bob Dury will be much better for book style examples. He's a recent arrival but has been putting in a lot of hours on testing each one. He's always asking on the forum about finer details of certain instructions - https://forums.parallax.com/discussion/173558/notes-on-propeller-might-be-helpful-for-new-user#latest

  • As a follow-up on this, I'm currently struggling to read the data using the smartpin. I transfer it into the LUT (as it's 768 bytes both in/out), and from there print it on the console for now.

    The following is the core SPI device routine that waits for CS to be asserted, and then attempts to read data in 32 bit words. This works somewhat but the data in the lut does not look as expected. My current assumption is that somehow the inner loop not working as expected and simply spins to read the last received bytes. But this might be wrong.

    pri spi()
    org
           ' reset our pointers
           mov incoming_p, #0
           mov outgoing_p, #SPI_BUFFER_SIZE
    
           dirl #CODI                    'Reset receiver Smart Pin
           wrpin sync_rx_mode, #CODI     'Set sync receiver mode
           wxpin #%1_11111,    #CODI     ' Acquire 32 bits, and
           dirh #CODI                    'Enable Smart-Pin sync receiver
    
           ' SPI receive loop
    .wait_cs_low
           testp  #CS      wz
           nop
    if_z   jmp      #.wait_cs_low
    
    .input_loop
           testp #CODI      wc                       'Wait in loop IN flag = set
           nop
    if_nc  jmp #.input_loop                   'If no C flag, repeat testing
           rqpin rcvd_data, #CODI
           rev   rcvd_data
           wrlut rcvd_data, incoming_p
           add   incoming_p, #1
    
           testp   #CS   wz
           nop
    if_nz  jmp      #.input_loop
           ret
    
    sync_rx_mode    long  P_MINUS1_B | P_SYNC_RX
    rcvd_data   long  $00
    incoming_p      long  $00
    outgoing_p      long  SPI_BUFFER_SIZE
    
    end
    

    The data I'm sending are 768 bytes counting from 0 to 768 (which of course get truncated to 0..255). See

    void fillBuffer(uint8_t *pBuffer) {
      uint8_t counter = 0;
      for (size_t i = 0; i < sizeOfInputFrame(kDefaultSampleCount); ++i) {
        pBuffer[i] = counter++;
      }
    }
    

    So what I would expect are three times the bytes 0..255 after another.

    However the data I print out looks like this:

    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    FCFDFEFF:FCFDFEFF:FCFDFEFF:FCFDFEFF
    

    This is the last LONG transferred, repeated over. I can kind of verify this when changing the data in my buffer like this:

    void fillBuffer(uint8_t *pBuffer) {
      uint8_t counter = 0xff;
      for (size_t i = 0; i < sizeOfInputFrame(kDefaultSampleCount); ++i) {
        pBuffer[i] = counter--;
      }
    }
    

    This just reverts the data, so three blocks from 255..0.

    I get this:

    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:3020100:3020100:3020100
    3020100:F0E0D0C:F0E0D0C:F0E0D0C
    F0E0D0C:F0E0D0C:F0E0D0C:F0E0D0C
    F0E0D0C:F0E0D0C:F0E0D0C:F0E0D0C
    F0E0D0C:F0E0D0C:F0E0D0C:F0E0D0C
    

    So most of the values are what would be expected:

    3, 2, 1, 0

    the last 4 bytes transferred.

    But what is also visible: every now and then there is other data interspersed. But also repeated.

    My intuition was that maybe I need to use rdpin instead of rqpin to acknowledge and wait for the next full long to arrive.

    But when changing this instruction, the system stops working - I presume I'm stuck inside the loop.

    Any hints very welcome.

  • A quick follow-up: my idea that the input_loop is too fast I could confirm by counting the number of read longs and printing the number - I spin ~4500 times instead of the expected 192.

  • evanhevanh Posts: 15,171
    edited 2021-09-21 16:37

    You're on to it. :) Definitely need to test the smartpin's (CODI) IN state to identify if new data received. And use RDPIN, instead of RQPIN, to clear IN state.

  • @evanh as usual, once writing things up (and talking to my partner over burger & fries about my day, she's an engineer, too), my palm and my face connected. So I powered up my machine again, and of course I have to use rdpin, but then need to also count the actual words and terminate my loop. Otherwise I'd be stuck on the last transmission. Doh, to quote a famous fictional father.

    I will try and setup streaming the output buffer from LUT next, steel yourself against the next barrage of questions ;)

    For completeness sake, here is a buffer output, exactly as expected:

    FFFEFDFC:FBFAF9F8:F7F6F5F4:F3F2F1F0
    EFEEEDEC:EBEAE9E8:E7E6E5E4:E3E2E1E0
    DFDEDDDC:DBDAD9D8:D7D6D5D4:D3D2D1D0
    CFCECDCC:CBCAC9C8:C7C6C5C4:C3C2C1C0
    BFBEBDBC:BBBAB9B8:B7B6B5B4:B3B2B1B0
    AFAEADAC:ABAAA9A8:A7A6A5A4:A3A2A1A0
    9F9E9D9C:9B9A9998:97969594:93929190
    8F8E8D8C:8B8A8988:87868584:83828180
    7F7E7D7C:7B7A7978:77767574:73727170
    6F6E6D6C:6B6A6968:67666564:63626160
    5F5E5D5C:5B5A5958:57565554:53525150
    4F4E4D4C:4B4A4948:47464544:43424140
    3F3E3D3C:3B3A3938:37363534:33323130
    2F2E2D2C:2B2A2928:27262524:23222120
    1F1E1D1C:1B1A1918:17161514:13121110
    F0E0D0C:B0A0908:7060504:3020100
    FFFEFDFC:FBFAF9F8:F7F6F5F4:F3F2F1F0
    EFEEEDEC:EBEAE9E8:E7E6E5E4:E3E2E1E0
    DFDEDDDC:DBDAD9D8:D7D6D5D4:D3D2D1D0
    CFCECDCC:CBCAC9C8:C7C6C5C4:C3C2C1C0
    BFBEBDBC:BBBAB9B8:B7B6B5B4:B3B2B1B0
    AFAEADAC:ABAAA9A8:A7A6A5A4:A3A2A1A0
    9F9E9D9C:9B9A9998:97969594:93929190
    8F8E8D8C:8B8A8988:87868584:83828180
    7F7E7D7C:7B7A7978:77767574:73727170
    6F6E6D6C:6B6A6968:67666564:63626160
    5F5E5D5C:5B5A5958:57565554:53525150
    4F4E4D4C:4B4A4948:47464544:43424140
    3F3E3D3C:3B3A3938:37363534:33323130
    2F2E2D2C:2B2A2928:27262524:23222120
    1F1E1D1C:1B1A1918:17161514:13121110
    F0E0D0C:B0A0908:7060504:3020100
    FFFEFDFC:FBFAF9F8:F7F6F5F4:F3F2F1F0
    EFEEEDEC:EBEAE9E8:E7E6E5E4:E3E2E1E0
    DFDEDDDC:DBDAD9D8:D7D6D5D4:D3D2D1D0
    CFCECDCC:CBCAC9C8:C7C6C5C4:C3C2C1C0
    BFBEBDBC:BBBAB9B8:B7B6B5B4:B3B2B1B0
    AFAEADAC:ABAAA9A8:A7A6A5A4:A3A2A1A0
    9F9E9D9C:9B9A9998:97969594:93929190
    8F8E8D8C:8B8A8988:87868584:83828180
    7F7E7D7C:7B7A7978:77767574:73727170
    6F6E6D6C:6B6A6968:67666564:63626160
    5F5E5D5C:5B5A5958:57565554:53525150
    4F4E4D4C:4B4A4948:47464544:43424140
    3F3E3D3C:3B3A3938:37363534:33323130
    2F2E2D2C:2B2A2928:27262524:23222120
    1F1E1D1C:1B1A1918:17161514:13121110
    F0E0D0C:B0A0908:7060504:3020100
    
Sign In or Register to comment.