Shop OBEX P1 Docs P2 Docs Learn Events
SmartPin Synchronous Serial Transmit - Page 2 — Parallax Forums

SmartPin Synchronous Serial Transmit

2

Comments

  • evanhevanh Posts: 15,126
    Solved it I think. You've got a startup out of sync problem with the data word length against the 8 clock pulses. It never recovers. This might be something to be wary of at the start of any packet, ie: make sure clock and data are in sync.

    Add a DIRL #clkout at the top of the program, before the WRPIN. May as well do the #txout too.
  • evanhevanh Posts: 15,126
    Without the DIRL, what can happen is the DIR can already be high and the moment WRPIN sets the mode it acts. Which for transition mode may start streaming clocks so that the moment the sync.serial is enable/set will be shifting without you having told it to.
  • Thank you evanh! I will give this a try this evening. I agree, it seems to be some sort of race condition.

    I thought I was going crazy for a moment!
  • jmgjmg Posts: 15,140
    evanh wrote: »
    Solved it I think. You've got a startup out of sync problem with the data word length against the 8 clock pulses. It never recovers. This might be something to be wary of at the start of any packet, ie: make sure clock and data are in sync.
    To handle this, I thought Smart Pins has some ability to prepare (arm) a number of pins, and then start ?
    Even without that, the code seems to always have Tx Shifter load, right before Tx Clock load, so shouldn't that always have a fixed and small 2 Sysclk offset ?

    Or, do you mean the startup/configure sequence should always configure CLK first, so the pin is in a stable state, before it preps the TX connected to that clock pin ?
    The above code does not do that, and in a part that floats pins during reset and until users define them, there is no assumed starting pin state.
  • jmg wrote: »
    Or, do you mean the startup/configure sequence should always configure CLK first, so the pin is in a stable state, before it preps the TX connected to that clock pin ?
    The above code does not do that, and in a part that floats pins during reset and until users define them, there is no assumed starting pin state.
    I think he'll be happy when he tries this out tonight! Moving the CLK config before Tx, worked in PNut as well as with fastspin/loadp2...
    dirl    #clkout
        wrpin   trans,#clkout
        wxpin   ##$1000,#clkout     'set base period
        dirh    #clkout
    
        dirl    #txout
        wrpin   sync_tx,#txout      'sync tx
        wxpin   #%1_00111,#txout    'stop/start mode
        dirh    #txout          'enable smartpin
    
    serTest.png

    dgately
    1079 x 684 - 631K
  • ???
    The code works Ok in Pnut and spin2gui here on my P2-ES without any changes.
  • evanh wrote: »
    Without the DIRL, what can happen is the DIR can already be high and the moment WRPIN sets the mode it acts. Which for transition mode may start streaming clocks so that the moment the sync.serial is enable/set will be shifting without you having told it to.
    On reset the P2 sets all DIR bits low anyway.

    This still doesn't explain why it works for Terry in Pnut (most of the time?) but never from spin2gui.

    The code runs fine here from both pnut and spin2gui.
    I even tried loading from Python P2 loader as well and it worksfine too.
  • evanhevanh Posts: 15,126
    dgately wrote: »
    Moving the CLK config before Tx, worked in PNut as well as with fastspin/loadp2...

    Huh, you're right. I'd done that too and forgotten about it.
  • evanh wrote: »
    dgately wrote: »
    Moving the CLK config before Tx, worked in PNut as well as with fastspin/loadp2...

    Huh, you're right. I'd done that too and forgotten about it.
    Chainging the config order makes no difference here,it still works.
    Same scope images either way.
  • evanhevanh Posts: 15,126
    edited 2019-02-18 01:04
    I'm guessing it depends on prior X and Y. Maybe they can be indeterminate if not set. And Y isn't being set until after the first second.
    PS: I've been testing FPGA with v33j.
  • jmgjmg Posts: 15,140
    ozpropdev wrote: »
    On reset the P2 sets all DIR bits low anyway.
    Yes, but that just floats the pins.
    Ideally, you want the Sync CLK pin firmly defined before you enable any connected-shifter, otherwise you have a lottery of a possible first edge on init.


  • evanhevanh Posts: 15,126
    And from the docs:
    During reset (DIR=0), IN is low, the output is low, and Y is set to zero.

    My take from that is, if DIR is high then, any pre-existing Y value is a case for automatic transitions on mode config. And they don't stop until Y counts to zero.

  • evanhevanh Posts: 15,126
    edited 2019-02-18 01:34
    Actually, dgately may have identified the most important part - placing the DIRH #txout at the end of the init code.

    EDIT: Like JMG says, clkout needs to be well defined before txout is engaged.
  • evanh wrote: »
    Actually, dgately may have identified the most important part - placing the DIRH #txout at the end of the init code.
    Actually, that part of the code was as ke4pjw had written it... I just added the dirl instructions and moved the clk config portion above the txout config portion. So, that's all from JMG's suggestion.
  • It would seem that my P2-ES board has lower noise than Terry's board.
    As has been pointed out the clock config should be done before tx config.
    This doesn't seem to matter on my board as I've mentioned above.
    To replicate the $1c error I did the following in between tx and clock config.
       drvh  #clkout
      fltl #clkout
    
    A single clock throws the sync transmitter out of order.
    Scope images now show $1c instead of $C1 as Terry observed.

    So Clock before Tx config and your good to go. :cool:
  • evanhevanh Posts: 15,126
    Yep, a bit of both. In my case every DIR was indeed high before init. I had a devil of a time getting anything sensible for a while.
  • Glorious! Thank you guys *SO* much! Works perfect with pnut, spin2gui, and boot from SD.

    Someone may want to add this to the tricks and traps thread.

    Again, thank you!
    con
    	clkout = 9
    	txout = 8
    
    dat	org
    
    
    	dirl    #clkout
    	wrpin	trans,#clkout
    	wxpin	##$1000,#clkout		'set base period
    	dirh	#clkout
    
    	dirl    #txout
    	wrpin	sync_tx,#txout		'sync tx
    	wxpin	#%1_00111,#txout	'stop/start mode
    	dirh	#txout			'enable smartpin
    
    	SHL data,#32-8  ' Set MSB First
    	REV data	' Set MSB First
    
    
    loop	waitx	##20_000_000
    	wypin	data,#txout		'data
    	wypin	#16,#clkout		'start clock, tx data
    
    busy	testp	#clkout wc
    	if_nc	jmp	#busy
    	rdpin	pa,#clkout
    	wypin	#0,#txout
    
    	jmp	#loop
    
    sync_tx	long	%1001 << 24 | %1_11100_0  'b pin = current pin+1 and inverted
    trans	long	%1_00101_0
    data	long	$C1
    
    
  • ke4pjw wrote: »
    ...Someone may want to add this to the tricks and traps thread...

    Just do it, It is just a normal thread...

    Cool that you nailed it down.

    Enjoy!

    Mike
  • The code examples work properly. How can I get inverted clock pulses? I want a logic-1 output on the idle clock pin and logic-0 pulses so a device can sample on the logic-1 to logic-0 transition. See figure below. Thanks. --Jon
    755 x 299 - 37K
  • evanhevanh Posts: 15,126
    edited 2020-06-11 18:04
    Detailed as bit "O" in the low-level P field modes - https://forums.parallax.com/discussion/comment/1452036/#Comment_1452036

    eg: In Terry's example above:
    trans	long	%001000000_01_00101_0
    
  • Thanks, evanh, I tried that. But the result shows the first negative-going edge of the clock signal coincident with the negative-going edge at the end of the first bit, a logic-1. So the first bit sent gets "lost." Seems to me the clocking edge should appear in the middle of the bit time. Any ideas? --Jon

    800 x 480 - 19K
  • Here's my code:
    CON
            clkout = 20	' Pin P20
    	txout  = 21     ' Pin P21
    
    dat	org
    	
    	wrpin	sync_tx_mode,     #txout        'Set up sync tx mode
    	wxpin	#%1_00111,        #txout	'Set up stop/start mode
    	dirh	#txout			        'Enable Smart Pin
    
    	wrpin	clock_mode,       #clkout       'Set pin P21 as transition-output mode
    	wxpin	##$1000,          #clkout        'Set base period for transition output
    	dirh	#clkout                         'Enable P21 as clock-output
    
    .loop	waitx	##10_000_000			'Delay between transmissions
    	wypin	#$71,             #txout        '8-bit data to transmit: 01110001
    	wypin	#16,              #clkout       'Start clock, transmit data
    	jmp	#.loop                          'Loop to transmit again and again
    
    sync_tx_mode    long  %0000_1111_000_0000000000000_01_11100_0  'B pin = current pin-1
    
    clock_mode	long  %0000_0000_000_0000001000000_01_00101_0  'Transition-mode setup
    
    'Courtesy of ozpropdev via Parallax Forum
    
  • evanhevanh Posts: 15,126
    The tx pin is using falling edge as per the B field. For rising edge use:
    sync_tx_mode    long  %0000_0111_000_0000000000000_01_11100_0  'B pin = current pin-1
    
  • evanhevanh Posts: 15,126
    Oh, and rule of thumb is setup the SPI clock pin first. That way when the data pin is setup the clock is already at idle level.
  • Thanks, evanh. Appreciate the help. Swapped the pin-setup sequence and the scope signal look good. --Jon
  • Back for more help... Looks like the synchronizing clock gets transmitted one cycle too late in one mode. The attached scope image (0009) shows the clock and data output when I run the program below. The sync_tx_mode BBBB bits are set for %1111. The clock output appears delayed so it does not generate an edge for the logic-1 LSB. Data to send is $85, transmitted as %10100001. (Same results on logic analyzer.)

    When I change the BBBB bits in sync_tx_mode to %0111 the scope shows the proper negative-going clock edge. Also shown in second attached scope image (0008).

    I'm working on revisions to the Propeller-2 Smart-Pin docs and want to include an example of positive-going clocking and negative-going clocking. I appreciate all help offered. --Jon
    CON
            clkout = 20	' Pin P20
    	txout  = 21     ' Pin P21
    
    dat	org
    		
    	wrpin	sync_tx_mode,     #txout        'Set up sync tx mode for pin 21
    	wxpin	#%1_00111,        #txout	'Set up stop/start mode, X[5] = 1, 8 bits
    	dirh	#txout			        'Enable Smart Pin
    	
    	wrpin	clock_mode,       #clkout       'Set pin P20 as transition-output mode
    	wxpin	##$1000,          #clkout        'Set base period for transition output
    	dirh	#clkout                         'Enable P20 as clock-output
    
    .loop	waitx	##10_000_000			'Delay between transmissions
    	wypin	#$85,             #txout        '8-bit data to transmit: 10000101
    	wypin	#16,              #clkout       'Start clock, transmit data
    	
    	jmp	#.loop                          'Loop to transmit again and again
    
    sync_tx_mode    long  %0000_0111_000_0000000000000_01_11100_0  'B pin = current pin-1
    
    clock_mode	long  %0000_0000_000_0000001000000_01_00101_0  'Transition-mode setup
    
    800 x 480 - 19K
    800 x 480 - 19K
  • evanhevanh Posts: 15,126
    edited 2020-06-13 00:12
    Well, there is at least four valid combinations for SPI clocking. And there is more if the clock idle state is treated separately from the clocking edge.

    And incoming vs outgoing clocking can also double the combinations again, ie: the master data out can be transitioned on the same clock edge as the slave data in reads. Normally SPI specifically avoids this possibility but the prop2 has such a lot of stages in the I/O that it's a perfectly reliable way of handling SPI.

    I wouldn't be able to fit all the examples in one post!

  • evanhevanh Posts: 15,126
    edited 2020-06-13 04:35
    JonTitus wrote: »
    Back for more help... Looks like the synchronizing clock gets transmitted one cycle too late in one mode. The attached scope image (0009) shows the clock and data output when I run the program below.
    Ha, I see what you mean. I've not actually tried to use the smartpins as intended for this. My experiments were always operating at the edge where staging trickery was a given.

    Okay, so it seems that only CPHA=0 is correctly supported:
    'SPI clock mode CPHA=0, CPOL=0
    sync_tx_mode	long  %0000_1111_000_0000000000000_01_11100_0  'B pin = current pin-1
    clock_mode	long  %0000_0000_000_0000000000000_01_00101_0  'Transition-mode setup
    
    'SPI clock mode CPHA=0, CPOL=1
    sync_tx_mode	long  %0000_0111_000_0000000000000_01_11100_0  'B pin = current pin-1
    clock_mode	long  %0000_0000_000_0000001000000_01_00101_0  'Transition-mode setup
    

    PS: See https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#Clock_polarity_and_phase

    PPS: When operating with bit rate at a close fraction of sysclock rate, the phase can be altered by taking advantage the number of sysclock'd stages in from the B pin and back out the tx pin.

  • evanhevanh Posts: 15,126
    edited 2020-06-13 05:00
    Actually, even at a sedentary pace you can still use the fact that those stages exist anyway. They still present a significant hold time that any real hardware slave device will be happy with. Meaning the clock-out and clock-in can be treated as the same polarity rather than the nominal SPI way of using opposing polarities.

    It just looks bad at bitrate of sysclock/8192 is all.

  • larryvclarryvc Posts: 42
    edited 2020-06-13 21:18
    Interestingly, it's only the first group after the synchronous serial transmit Smartpin is enabled that indicates the loss of the first clock pulse. Everything sent after that is correct for either BBBB = 0111 or BBBB = 1111. Scope works today, capture does not, sorry. For the code below, trigger on txout pin rising, 10 MHz sample rate gave a nice display when zoomed in.
    CON
            clkout  = 20 ' Pin P20
            txout   = 21 ' Pin P21
    
            baseperiod = $100               ' 256 decimal
            bytedelay = baseperiod * 16     ' 4096 decimal
    
    dat org
            dirl    #clkout
            wrpin   clock_mode,     #clkout 'Set pin P20 as transition-output mode
            wxpin   #baseperiod,    #clkout 'Set base period for transition output
            dirh    #clkout                 'Enable P20
            wypin   #48,            #clkout 'Start clock first
    
            dirl    #txout
            wrpin   sync_tx_mode,   #txout  'Set up sync tx mode for pin 21
            wxpin   #%1_00111,      #txout  'Set up stop/start mode, X[5] = 1, 8 bits
            dirh    #txout                  'Enable P21
    
            wypin   #$00,           #txout  '8-bit data to transmit: 00000000
            waitx   ##bytedelay
    
            wypin   #$85,           #txout  '8-bit data to transmit: 10000101 LSB transmitted first
            waitx   ##bytedelay
    
    
            wypin   #$00,           #txout  '8-bit data to transmit: 00000000
            waitx   ##bytedelay
    
    .loop   jmp     #.loop                  'We're done, loop forever
    
    sync_tx_mode    long    %0000_0111_000_0000000000000_01_11100_0  'B pin = current pin-1
    
    
    clock_mode      long    %0000_0000_000_0000001000000_01_00101_0  'Transition-mode setup
    

    EDIT: Corrected a couple of comments.
    EDIT2: Updated code to change the delay from ##3000 to ##4096.
Sign In or Register to comment.