Shop OBEX P1 Docs P2 Docs Learn Events
How to phase-sync two counters of one cog? — Parallax Forums

How to phase-sync two counters of one cog?

ul5255ul5255 Posts: 14
edited 2012-09-10 16:17 in Propeller 1
Dear all,

I'd like to use the two counters of one cog to output a signal
in PLL mode. Both counters shall produce the signal with the
same frequency *and* phase.

My approach is to pre-load the PHSB register with a value
of 2x FRQA (I have previously verified that after the operation
'mov frqb, f' the value of PHSA already advanced by
2x FRQA):
[FONT=courier new]
mov ctra, ctraval      ' PLL square wave at pin 15[/FONT][FONT=courier new]
mov ctrb, ctrbval      ' PPL square wave at pin 16

mov phsb, phase_delta  ' advance PHSB by 2*FRQA because
                       ' counter A starts one MOV
                       ' instruction before counter B
  
mov frqa, f            ' start counter A
mov frqb, f            ' start counter B (counter A already
                       '  counts!)

mov DIRA, d            ' finally set pin 15+16 as output
[/FONT]
After this I hoped that both counters would generate the
signal with the same phase. For this I use another cog's counter
A to count the number of times where the two pins 15 and 16
have different logic levels. I let this counter run for ~ 10 sec.
Then I serial.dec(PHSA) back to the PC. Unfortunately that
value is never zero. To make matters worse that value is not
a constant.

I can imagine to dynamically adjust the PHSB value of the
signal generating cog until the phase difference between both
counters is getting (close to) zero but I hope there is a
better way to do this (perhaps start both counter at the
same time?) ...

Any ideas?

Cheers,
ul5255.

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-10 14:39
    This is the way I do it:
    mov phsb, f  ' advance PHSB by 4*FRQA.
    shl phsb,#2                      
                            
    mov frqa, f            ' Set frqa (does not start counter).
    mov frqb, f            ' Set frqb (does not start counter).                      
    
    mov ctra, ctraval      ' Start ctra.
    mov ctrb, ctrbval      ' Start ctrb.
    
    mov DIRA, d            ' finally set pin 15+16 as output
    

    -Phil
  • ul5255ul5255 Posts: 14
    edited 2012-09-10 15:16
    Thanks Phil. I tried your solution. What I get now is occasionally a pretty good alignment between the two signals.
    In other cases (uploading the exact same code to the propeller) the signals are almost 180 degree phase-shifted.
    The alignment is never 100% ...
    Is this because it is essentially unpredictable when/how the PLL locks to the programmed frequency?

    -ul5255
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-10 15:19
    ul5255,

    As long as the PLL multiplier is x1 or greater, that should work. If it's less than that, you're better off just going the NCO route, since you won't be able to predict the phase relationship.

    -Phil
  • ul5255ul5255 Posts: 14
    edited 2012-09-10 15:33
    Phil,
    Here is the complete code, my bench-top frequency counter agrees that the
    frequency is ~ 3.56MHz. My two channel scope and the cog#0
    logic counter both show that occasionally one pin has the inverted
    square wave of the other ...
    I also completely removed the Serial code to rule out any side effects but
    the result was the same.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_120_000
    
      rx_pin = 31
      tx_pin = 30
    
      a_pin = 15
      b_pin = 16
    
    OBJ
      serial      : "FullDuplexSerial"
        
    PUB Main
      serial.start(rx_pin, tx_pin, 0, 9_600)
      serial.rxflush
    
      cognew(@Tx, 0)
    
      ' give the other cog some time to set up counters
      waitcnt(clkfreq * 5 + cnt)
    
      ' every occurence is counted once
      FRQA := 1
      ' logic a_pin != b_pin
      CTRA := (% 00110 << 26) | (b_pin << 9) | (a_pin)
      
      waitcnt(10 * clkfreq + cnt)
    
      serial.dec(phsa)
    
    DAT
            org 0       
    
    Tx      mov phsb, f
            shl phsb, #2  
      
            mov frqa, f
            mov frqb, f
            
            mov ctra, ctraval
            mov ctrb, ctrbval
    
            mov DIRA, d
      
    :loop   jmp #:loop
    
    ctraval long % 00010 << 26 + % 010 << 23 + a_pin
    ctrbval long % 00010 << 26 + % 010 << 23 + b_pin
    
    d       long (|< a_pin) + (|< b_pin)
    
    f       long 373_293_056
    
            fit 496
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-10 15:51
    Your PLL multiplier is 0.5. As I stated, if it's less one, you will not be able to sync the counters deterministically. Although 3.56 MHz is technically out of range to drive the PLL, you might try it anyway and use a x1 multiplier. The only other thing I can think of is to test the synchronization with your program and, if the counters are out of sync, restart them.

    -Phil
  • ul5255ul5255 Posts: 14
    edited 2012-09-10 16:04
    I am feeding the PLLs with 3.56MHz NCO and now it works pretty good. Over a 10sec period I still get ~ 500,000 events where both pins don't have the same logic level but this I can probably fine tune with small adjustments to the PHSB register.

    Thanks a lot, Phil !
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-10 16:12
    You can't adjust phsb while the counter is running, unfortunately. The way to do it is to add, then subtract, a small increment to frqb.

    -Phil
  • ul5255ul5255 Posts: 14
    edited 2012-09-10 16:17
    good to know ... just started to manipulate PHSB ... you saved me some more time :thumb:
Sign In or Register to comment.