Shop OBEX P1 Docs P2 Docs Learn Events
Strange timing behavior — Parallax Forums

Strange timing behavior

skywatcherskywatcher Posts: 7
edited 2012-10-16 17:21 in Propeller 1
Hello @ all :smile:

I wanted to measure the frequency of an oscillator (about 30 kHz sqare wave) with the Propeller. Because measuring only one pulse gives not enough resolution for my purpose, i decided to wait for multiple H/L and L/H transitions before capturing the timer end value. When i looked at the results, i saw a jitter of several clock cycles. First i thought that my input signal may have this jitter, but i saw almost the same amount of jitter for every input signal, regardless of its source. It should be very unlikely that different signal sources have exactly the same amount of jitter. So i programmed a second propeller chip to generate a 'clean' signal and connected it to the first one. The jitter remained the same. Ok, maybe it's some sort of PLL jitter... then i used one and the same Propeller chip for signal generation and measurement, and this should be absolutely free of jitter because it's the same clock source. The test code is attached below.

The strange thing is now: If i measure <= 12000 pulses (NCount := 12000) there is no jitter.

The results look like this:


29063957
29063957
29063957
29063957

But if i increase NCount to 12500, it looks like this:

30274949
30274957
30274949
30274957
30274949
30274957

There is a jitter of 8 clock cycles.

I have absolutely no explanation for this.
All variables are 32 bit so there should not be any overflow.

Can anyone explain this ?

Comments

  • jmgjmg Posts: 15,173
    edited 2012-10-16 14:09
    Looks to me like when you exit loop2, the Pin is HIGH, and then your re-sync tests for hi, which is already true.
    That first load needs to be truly edge locked, otherwise is actually depends on the path delays.

    In a well designed Reciprocal Counter, you should be able to also have a longer background average, which means no gaps in the samples.
    A single capture point is a good idea, and 'pivot' the code housekeeping around that.

    So something like
           waitpne pinA,pinA ' wait for falling edge
           waitpeq pinA,pinA ' wait for rising edge
           mov tstart,cnt    ' Power On Init, or you can remove and simply discard first result
           mov count, NCount  ' can load 1, in ignore first result choice
           
    :loop2 waitpne pinA,pinA   ' wait for falling edge
           waitpeq pinA,pinA   ' wait for rising edge
           mov tend,cnt        ' capture end time
           djnz count, #:loop2
           
           mov tmp,tend        ' copy into temporary variable
           sub tmp,tstart      ' subtract start time from end time
           mov tstart, tend    ' make last capture, new start time 
           mov count, NCount
    '
           wrlong tmp, PAR     ' write result to hub ram location, can jitter
           jmp #:loop2          
    
    The first 3 lines can be removed, if you simply discard the first result.
  • StefanL38StefanL38 Posts: 2,292
    edited 2012-10-16 14:15
    Hi Skywatcher,

    herzlich willkommen - welcome to the propeller-forum

    looking into your code.

    Are you sure you want both cogs start with stack0 ?

    You also can use the counter-module to measure frequencies. I haven't done much with the counters yet.

    best regards
    Stefan
  • skywatcherskywatcher Posts: 7
    edited 2012-10-16 14:22
    @StefanL38:
    The results are written into the HUB RAM after the last sampling of the counter so thi should have no influence, especially as long as the writing is completed before the next falling edge, which is always the case.
    Additionally, the question remains why there is no jitter at <= 12000 pulses measurement, and there is jitter at 12500 pulses measurement.
  • jmgjmg Posts: 15,173
    edited 2012-10-16 14:39
    skywatcher wrote: »
    @StefanL38:
    The results are written into the HUB RAM after the last sampling of the counter so thi should have no influence, especially as long as the writing is completed before the next falling edge, which is always the case.

    Not quite, see #2, and try the code flow I just added.
    8 cycles is not random, it is dependent on what else is happening
  • skywatcherskywatcher Posts: 7
    edited 2012-10-16 14:53
    jmg wrote: »
    Not quite, see #2, and try the code flow I just added.
    8 cycles is not random, it is dependent on what else is happening

    I tested your code, and compared to my code the resulting measurements were some clock cycles higher, which is strange because the code in loop2 after the 'waitpeq' instruction should not have any influence on the result, because its execution time is well below the time of the 'high time' of the input signal. But it really looks like the jitter comes from the wrlong HUB instruction which is the only instruction in the whole loop with a variable execution time.
  • jmgjmg Posts: 15,173
    edited 2012-10-16 14:59
    skywatcher wrote: »
    I tested your code, and compared to my code the resulting measurements were some clock cycles higher, which is strange because the code in loop2 after the 'waitpeq' instruction should not have any influence on the result, because its execution time is well below the time of the 'high time' of the input signal. But it really looks like the jitter comes from the wrlong HUB instruction which is the only instruction in the whole loop with a variable execution time.

    Try it written like this
           
    :loop2 waitpne pinA,pinA   ' wait for falling edge
           waitpeq pinA,pinA   ' wait for rising edge - true edge lock
           mov tend,cnt        ' capture end time
           djnz count, #:loop2
           
           mov tmp,tend        ' copy into temporary variable
           sub tmp,tstart      ' subtract start time from end time
           wrlong tmp, PAR     ' write result to hub ram location
           mov count, NCount
           waitpeq pinA,pinA   ' << oops, this already hi
           mov tstart, cnt     ' << NOT edge locked, but transit-delayed from the true edge locked above 
    
    

    That is the benefit of a single load point.
  • skywatcherskywatcher Posts: 7
    edited 2012-10-16 16:09
    It's completely weird... i inserted 10 NOPs after the 'wrlong' in the code you posted above, and then the average result was about 40 clock cycles *lower* than without the NOPs.
    I would have expected to be unchanged, or maybe 40 clocks higher, but not lower. This is completely beyond my understanding.
  • jmgjmg Posts: 15,173
    edited 2012-10-16 16:22
    skywatcher wrote: »
    It's completely weird... i inserted 10 NOPs after the 'wrlong' in the code you posted above, and then the average result was about 40 clock cycles *lower* than without the NOPs.
    I would have expected to be unchanged, or maybe 40 clocks higher, but not lower. This is completely beyond my understanding.

    Which code ? The code in #2 should be immune, as it has a single timing point,
    The code in #7 is the error simply rephrased (not fixed), to hopefully make it clearer.

    The bottom read of CNT is not edge locked, but is a transit-time-added to the real edge pivot, which is further up.
    Thus adding NOPS should lower the next difference, as that start is incorrectly late, and pushed later by the NOPs.

    You could fix #7 by adding a waitpne pinA,pinA, to get a real edge lock again, but as that then clones the code at Loop2, I personally prefer a single-point-of read, as that avoids these transit-time issues.
  • Mark_TMark_T Posts: 1,981
    edited 2012-10-16 16:31
    You are not synchronizing at the start of the PASM - you simply do waitpeq. The pin has a finite chance of already being low, in which no wait happens. You must do waitpne then waitpeq to synchronise to an edge.

    [edit: Doh, didn't notice other replies!]
  • skywatcherskywatcher Posts: 7
    edited 2012-10-16 16:33
    @jmg:
    Ok, you are right... in code #2 the NOPs have no effect. I think i have to go to bed and continue tomorrow, it's already 1:30 am here... anyway, thanks for your help. :-)

    @all:
    Is there any data available about the phase noise of the Propeller PLL ? In the datasheet there is no info about this.
  • jmgjmg Posts: 15,173
    edited 2012-10-16 16:44
    skywatcher wrote: »
    @all:
    Is there any data available about the phase noise of the Propeller PLL ? In the datasheet there is no info about this.

    Not that I have seen, but I think it is a true PLL, not some delay-fudged version.

    You could test this with two Props, and not quite the same Crystal/Osc, to give you an Audible beat.
    Use of a sound card spectrum analyzer should give the jitter.
  • skywatcherskywatcher Posts: 7
    edited 2012-10-16 16:53
    I have now tested your code #2 again with a 2nd Propeller (with a seperate clock source, of course) which generates a squarewave signal. The measured jitter is now +/- 1 clock cycle, so it could not be better. :)
  • Mark_TMark_T Posts: 1,981
    edited 2012-10-16 16:55
    The system clock PLL is typically fed from a xtal, whereas the counter one's are often fed from jittery NCO. I can't find reference to PN measurements on either - someone have suitable test equipment?
  • jmgjmg Posts: 15,173
    edited 2012-10-16 17:01
    skywatcher wrote: »
    I have now tested your code #2 again with a 2nd Propeller (with a seperate clock source, of course) which generates a squarewave signal. The measured jitter is now +/- 1 clock cycle, so it could not be better. :)

    Sounds good, you should also be able to see the drift between two Oscs - try soldering one, then watch it cool.
    On your numbers, you have a LSB in the region of 33ppb.

    On the jitter front, if you can find two Oscs/Xtals apx 500Hz apart, you can resolve to
    1/(5e6+500)-1/(5e6+450) = -1.9996e-12 seconds - ie a 50Hz change, is ~2 picoseconds
  • skywatcherskywatcher Posts: 7
    edited 2012-10-16 17:07
    Yes, that's the reason why i chose to accumulate 12500 measurements, this gives me 12.5 ns / 12500 = 1 ps (theoretical and averaged) resolution.

    I can see the two oscillators drifting away very slowly. Looks nice. :)
  • kuronekokuroneko Posts: 3,623
    edited 2012-10-16 17:21
    FWIW, given the setup in your posted code the test pulse measures 2022 cycles. With NCount = 12500 you should have expected 25275000 cycles being measured (instead of ~4955/4947A, big hint here). Also, using NCount = 1001 shows the same jitter (even worse in fact). It all boils down - as has been stated before - to not sync'ing again before measuring the start time (i.e. waitpne after mov count, NCount). With that in place it works every time for me.

    The difference in measured values in the unsynchronised case is simply down to math (cycles/loop) and the fact that hub windows are only at 16n (start time is affected by wrlong timing).

    A timing for my setup
Sign In or Register to comment.