Shop OBEX P1 Docs P2 Docs Learn Events
[resolved][puzzle] Drifter, The — Parallax Forums

[resolved][puzzle] Drifter, The

kuronekokuroneko Posts: 3,623
edited 2012-01-29 20:52 in Propeller 1
The attached program upsets the video h/w to generate a 32MHz pixel clock based on an 80MHz system clock, i.e. one pixel lasts 2.5 system clocks. After we synchronised to the waitvid hand-off point (WHOP) we delay for a frame and subsequently use a cmp insn in a 40 cycle loop (16 pixels per frame, 16 * 2.5 = 40 system clocks). Which works well up to a point, then the WHOP has drifted into the neighbouring insns and the video h/w outputs a guard pattern instead of the intended match pattern (demoboard LED bar). This is no surprise given that the frqx setup is not a power of two value.

Objective: Stabilise the WHOP so it stays within the designated compare insn.
waitvid zero, #0
                mov     dira, mask              ' drive outputs
'-----------------------------------------------
                [COLOR="orange"]waitvid zero, #0[/COLOR]                ' sync point

                [COLOR="blue"]mov     cnt, cnt[/COLOR]                '
                [COLOR="blue"]add     cnt, #9{14} + 19[/COLOR]        '
                [COLOR="blue"]waitcnt cnt, #0[/COLOR]                 ' adjust for one frame
'-----------------------------------------------
:loop           [COLOR="red"]cmp     match, #0[/COLOR]               ' WHOP
                cmp     guard, #0
                cmp     guard, #0
                cmp     guard, #0
                cmp     guard, #0               ' +20

                cmp     guard, #0
                cmp     guard, #0
                cmp     guard, #0
                cmp     guard, #0
                jmpret  guard, #:loop nr        ' +40

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-29 11:51
    The problem is that the correct value for frqa is $1999_9999.9999999..., not $1999_9999 (i.e. 429,496,729.6). The following code dithers frqa between $1999_999a and $1999_9999 on a 60:40 duty cycle, which averages out to the correct fractional setting:
    :loop           cmp     match, #0               ' WHOP
                    add     frqa,  #1
                    cmp     guard, #0
                    cmp     guard, #0
                    cmp     guard, #0               ' +20
    
                    cmp     guard, #0
                    cmp     guard, #0
                    sub     frqa,  #1
                    cmp     guard, #0
                    jmpret  guard, #:loop nr        ' +40
    

    So far, it hasn't slipped.

    -Phil

    Addendum: 'Checked back after an hour; still no slippage evident.
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-29 17:27
    Nice one, Phil! That said, given that (nearly) everyone is complaining of not having enough cycles in their video loop(s) what about a solution where we only need to sacrifice a single instruction inside the loop?

    @all: The fact that puzzle and Phil both start with the letter P doesn't mean that only he can participate!
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-29 20:38
    You could write an appropriate constant value to phsa immediately following each waitvid to force continued coherency. This would do in one instruction what incrementing, then decrementing, frqa does in two.

    -Phil
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-29 20:52
    Yes, that's the idea. We just want to avoid the waitvid please. Using it would defeat the point of sync'ing.

    The original solution simply sampled an appropriate phsa which is then inserted in the loop later (at the same offset). While picking a hard-wired value works, care must be taken to pick one far enough away from the critical points. Also, given that we are sync'd already the new/forced value shouldn't upset the PLL from that point onward. FWIW, using $19999999 gives you $04444444 stable NCO cycles which amounts to ~9sec @80MHz. Plenty of room.
    CON
      _clkmode = XTAL1|PLL16X
      _xinfreq = 5_000_000
    
    PUB drifter
    
      cognew(@entry, 0)
        
    DAT             org     0
    
    entry           movi    ctra, #%0_00001_101     ' PLL, VCO/4
                    mov     frqa, frqx              ' 8MHz * 16 / 4 = 32MHz
    
                    movd    vscl, #1 << (12 - 9)    '  1 clock  per pixel
                    movs    vscl, #16               ' 16 clocks per frame
                    
                    movd    vcfg, #2                ' pin group
                    movs    vcfg, #%0_11111111      ' pins
                    movi    vcfg, #%0_01_0_00_000   ' VGA, 2 colour mode
    
                    rdlong  cnt, #0                 '
                    shr     cnt, #10                ' ~1ms
                    add     cnt, cnt                '
                    waitcnt cnt, #0                 ' PLL needs to settle
    
                    waitvid zero, #0
                    mov     dira, mask              ' drive outputs
    '-----------------------------------------------
                    waitvid zero, #0                ' sync point
    
                    mov     cnt, cnt                '
                    add     cnt, #9{14} + 19        '
                    waitcnt cnt, #0                 ' adjust for one frame
    '-----------------------------------------------
                    cmp     match, #0       {0}     ' WHOP                   
                    mov     sync, frqa      {1}     ' frqa * 1               
                    add     sync, frqa      {2}     ' frqa * 2                
                    add     sync, phsa      {3}     ' frqa * 2 + phsa(-2)   (%%)
    
                    mov     cnt, cnt                '
                    add     cnt, #9{14} + 10        '
                    waitcnt cnt, #0                 ' complete sample frame
    '- - - - - - - - - - - - - - - - - - - - - - - -
    :loop           [COLOR="red"]cmp     match, #0[/COLOR]       {0}     ' WHOP                    
                    cmp     guard, #0       {1}                              
                    cmp     guard, #0       {2}                               
                    mov     phsa, sync      {3}     ' rewind/lock           (%%)
                    cmp     guard, #0               ' +20
    
                    cmp     guard, #0
                    cmp     guard, #0
                    cmp     guard, #0
                    cmp     guard, #0
                    jmpret  guard, #:loop nr        ' +40
    
    ' initialised data and/or presets
    
    mask            long    $00FF0000
    frqx            long    $19999999               ' clkfreq/10 (stable for ~9 sec, $0444_4444 NCO cycles)
    
    match           long    $24242424
    guard           long    $3C3C3C3C
    
    ' uninitialised data and/or temporaries
    
    sync            res     1
    
                    fit
    
    CON
      zero = $1F0   ' par
      
    DAT
    
Sign In or Register to comment.