Shop OBEX P1 Docs P2 Docs Learn Events
About SPI_Spin.spin — Parallax Forums

About SPI_Spin.spin

caskazcaskaz Posts: 957
edited 2010-08-19 07:30 in Propeller 1
Hi everyone.

I found out SPI_Spin.spin inside Propeller Tool's folder.
I read this and I have question.
There is code below:
ClockDelay := ((clkfreq/100000 * _ClockDelay) - 4296) #> 381

At first I think that 4296 is overhead's time to call PostClock(_Cpin)[or PreClock].
But it seems different.

How do 4296&381 calculate?

Comments

  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-08-18 09:08
    caskaz,

    I'll have to look at this closer when I get a moment. I think the idea is that 4296 introduces an initial overhead offset as you suggested, where the 381 limits the minimum time allowed for the waitcnt instruction that would prevent a counter roll-over. That said, the below 'test' code should produce a clock pulse with a period of 20us (<- two clock Delays), but instead it's about 119us. Way off!! ... this might however be an artifact of Spin with this particular example. I originally wrote the code in PAsm and it might work fine there. The Spin version between instructions doesn't have the resolution of PAsm so it might actually take 119us with Spin.

    CON
        _clkmode = xtal1 + pll16x                           
        _xinfreq = 5_000_000
    
    ClockPin = 0
    ClockDelay = 10
    
    VAR
    long    Delay    
    
    PUB MainProg
        dira[ClockPin]~~
        Delay := (clkfreq/100000 * ClockDelay)-4296
        Clock(ClockPin,Delay)
    
    PUB Clock(Pin,_Delay)
        repeat 
          !outa[Pin]
          waitcnt(cnt+_Delay)
    
    
  • Ding-BattyDing-Batty Posts: 302
    edited 2010-08-18 13:13
    Beau, I think your test code is a little off. You have:
    Delay := (clkfreq/100000 * ClockDelay)-4296
    
    But clkfreq/100000 (that's one hundred thousand) for 80MHz is 800 clock cycles (10 usec) times 10, gives 8000 clock cycles, less 4296, so Delay is set to 3704.

    Since there are two Delays per period, you are delaying about 7400 clock cycles, which is more than 92 usec.

    It looks like you want the expression clkfreq/1000000 (one milloin) to get clock cycles per usec, so that Delay will be about 10 usec, which is 800 clocks, but subtracting 4296 gives a negative delay (or a very large positive delay). Probably not what you want, either.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-08-18 14:23
    caskaz,

    The timing is wrong for the SPI_Spin object. The SPI_Asm object has the correct timing based on this simple formula noted within the SPI_Asm object.
             Delay := 15            ''Clock delay
                                    ''  = 300ns + (N-1) * 50ns
    
                                    '' Example1:
                                    ''     A Delay of 5 would be 500ns
                                    ''     300ns + 4 * 50ns = 500ns
    
                                    '' Example2:
                                    ''     A Delay of 15 would be 1us
                                    ''     300ns + 14 * 50ns = 1000ns = 1us
    


    To correct the timing for the SPI_Spin code, the line that reads ...
    ClockDelay := ((clkfreq/100000 * _ClockDelay) - 4296) #> 381
    

    ... should read ...
    ClockDelay := ((clkfreq / 1000000 * _ClockDelay) - 915) #> 541
    

    ... here is a better detailed descriptiion ...
    ''                                                     Offset required to allign timing to 1us (See Timing Note)                                                                                                                                                                                                                                                                         
    ''                                                      &#61602;    
        ClockDelay := ((clkfreq / 1000000 * _ClockDelay) - 915) #> 541
    ''                                                              &#61600;
    ''                                                             Minimium number of clocks allowed
    ''  Timing Note:
    ''  A minimum raw value of of 541 equates to a minimum timing of 18.2us
    ''
    ''  Because our clock runs at 80MHz, a count of 80 equates to 1us.  So a value of 621 translates to 19.2us
    ''  To lock this to 19us rather than 19.2us we need to subtract 16 (or 1/5th of 80) from 621.  This leaves us with
    ''  a value of 605 resulting in a pulse width of 19us.  Ok, so how do you get 915 for an offset?
    ''
    ''  in the equation ... ClockDelay := ((clkfreq / 1000000 * _ClockDelay) - 915) #> 541 ...
    ''                  ... clkfreq / 1000000 can be simplified as 80 ... resulting in ...
    ''
    ''                  ... ClockDelay := ((80 * _ClockDelay) - 915) #> 541 ...
    ''                  ... further, if our _ClockDelay is 19, it can be simplified to ...
    ''
    ''                  ... ClockDelay := (1520 - 915) #> 541 ...
    ''                  ... 1520 minus the 605 noted above results in a value of 915
    ''
    ''    Note:
    ''          - because of Spin overhead, 18.2us is the minimium allowed delay.
    ''          - Delay resolution is 1us
    
  • caskazcaskaz Posts: 957
    edited 2010-08-18 21:00
    Thanks Beau.
    I checked waitcnt by Demo Board.
    System counter roll over on waitcnt(cnt + 556)
    557 is OK.
    This vary on each boards?

    I checked below;
    CON   
      _clkmode = xtal1 + pll16x                  ' System clock &#8594; 80 MHz
      _xinfreq = 5_000_000
    OBJ
      debug : "FullDuplexSerialPlus"             ' Serial COM
    PUB main | count, s, b
      debug.Start(31, 30, 0, 57600)              ' Start FullDuplexSerialPlus 
      waitcnt(clkfreq*3 + cnt)                       ' Wait for PST to get connected
      debug.tx(Debug#CLS)                        ' Clear the screen
      dira[0] := 1
      s := 0
      repeat
         count := cnt
         b := PostClock(s)
         count := cnt - count
         debug.dec(count)
         debug.tx(13)
    Pub PostClock(_Cpin)
        waitcnt(cnt+557)
        !outa[_Cpin]
        waitcnt(cnt+557)
        !outa[_Cpin]
    

    count is 4240.
    4240/2=2120 2120*0.0125usec=26.5usec
    80*27(usec) - 557 = 1603
    ClockDelay := ((clkfreq / 1000000 * _ClockDelay) - 1603) #> 557

    I measured Low-time by using osiloscope.
    time wass aproximately 20usec.
    I think spin cannot be 1u-resolusion.

    My idea is wrong?
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-08-18 21:17
    caskaz,

    I think we are speaking apples to apples here ... The 557 will vary depending on the waitcnt loop that you are using but will be consistent from propeller to propeller.

    See my post just prior to yours. For the SPI_Spin object the magic number is 541 ... and I too was getting about 20us (18.2us to be more precise.)
  • caskazcaskaz Posts: 957
    edited 2010-08-19 06:02
    Hi Beau.

    I don't understand well English. What does apples mean?
    Sorry, I perfectly cannot understand your post.

    When I checked code, I found strange.
    Code is below;
    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    PUB main | ClockDelay, s, b
    _ClockDelay := 10
    ClockDelay := ((clkfreq / 1000000 * _ClockDelay) - 915) #> 541
    dira[0] := 1
    s := 0
    outa[0] := 1
    repeat
      b := PostClock(s)
    
    PUB PostClock(_Cpin)
    waitcnt(cnt+ClockDelay)
    !outa[_Cpin]
    waitcnt(cnt+ClockDelay)
    !outa[_Cpin]
    

    Low-pulse is approximately 18usec.

    I replace PUB PostClock(_Cpin) below;
    PUB PostClock(_Cpin)
    waitcnt(cnt+541)
    !outa[_Cpin]
    waitcnt(cnt+541)
    !outa[_Cpin]
    
    It's same above code. But No pulse.

    When I changed waitcnt(cnt+557), there are pulses.

    I have no idea.
    Why?
  • kuronekokuroneko Posts: 3,623
    edited 2010-08-19 06:36
    waitcnt(cnt+541) takes slightly longer (to interpret) than waitcnt(cnt+ClockDelay), and that appears to be just long enough to exceed the minimum advance for waitcnt() which is required for not blocking for a full cycle.
    19                        waitcnt(cnt+541)
    Addr : 0048:          3F 91  : Register op CNT Read
    Addr : 004A:       39 02 1D  : Constant 2 Bytes - 02 1D - $0000021D 541
    Addr : 004D:             EC  : Math Op +
    Addr : 004E:             23  : WaitCnt(count)
    
    19                        waitcnt(cnt+ClockDelay)
    Addr : 0048:          3F 91  : Register op CNT Read
    Addr : 004A:             40  : Variable Operation Global Offset - 0 Read
    Addr : 004B:             EC  : Math Op +
    Addr : 004C:             23  : WaitCnt(count)
    
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-08-19 07:30
    caskaz,

    "I don't understand well English. What does apples mean?" - It just means we are talking about the same thing.
Sign In or Register to comment.