Shop OBEX P1 Docs P2 Docs Learn Events
[resolved] waitvid minimum timing — Parallax Forums

[resolved] waitvid minimum timing

kuronekokuroneko Posts: 3,623
edited 2010-08-04 17:43 in Propeller 1
To put it bluntly, it wasn't what I expected. Then again, what is? I tried to get a handle on this in the past but somehow didn't. Anyway, lets start with some prerequisites.

The video PLL is set to run at 20MHz, frame and pixel clocks are left at default values (4K/256). Which means at 80MHz a frame should last 16K cycles. I sample cnt in three places, at the start of the frame (after the last waitvid), immediately before waitvid for the current frame and also immediately after that one. Lets call them one, two and three in that order. Which means (three - one) gives us the cycle count for the frame (in clock cycles) and (three - two - 4) gives us the time spent in waitvid. One last thing, in order to not spent all the time waiting in waitvid I fill the gap with a defined waitcnt to consume all those unsused cycles.

                waitvid zero, zero
'-----------------------------------------------
 _one_          mov     eins, cnt               ' start of frame N

                mov     cnt, cnt                '
                add     cnt, delay              '
                waitcnt cnt, #0                 ' delay 14 + (delay - 9)
                
_two_           mov     zwei, cnt               ' end of frame N (sort of)
                waitvid zero, zero
'-----------------------------------------------
_three_         mov     drei, cnt               ' start of frame N+1



And here are the results:

' frame length = mov + (14 + (delay - 9)) + mov + waitvid
'        delay = frame length - mov - 14 + 9 - 4 - waitvid
'        delay = 4K*4 - 4 - 14 + 9 - 4 - 4+
'        delay = 16371 - 4+                        expected waitvid    measured
                                '                    cycle count      cycle count
  collect(16365)                ' -2 too early            6                6
  collect(16366)                ' -1 too early            5                5
  collect(16367)                ' +0 perfect match        4                4
  collect(16368)                ' +1 too late       16K + 4 - 1            4
  collect(16369)                ' +2 too late       16K + 4 - 2      16K + 4 - 2



So, like it or not, the minimum cycle time for a waitvid is 4. You'll notice that the measured timing for +1 too late is also 4 (it's not a typo). In this case the frame length is not 16K cycles but 16K+1 cycles. What remains to be investigated is how that affects the next frame, i.e. whether it can be off by one as well.

Make sure you check out other oddities listed here.

Comments

  • Bill HenningBill Henning Posts: 6,445
    edited 2010-04-08 19:16
    Thank you - VERY interesting analysis!

    This means that with careful coding even higher resolutions may be possible than I expected, based on the 5+ cycle rating of waitvid
    kuroneko said...
    To put it bluntly, it wasn't what I expected. Then again, what is? I tried to get a handle on this in the past but somehow didn't. Anyway, lets start with some prerequisites.

    The video PLL is set to run at 20MHz, frame and pixel clocks are left at default values (4K/256). Which means at 80MHz a frame should last 16K cycles. I sample cnt in three places, at the start of the frame (after the last waitvid), immediately before waitvid for the current frame and also immediately after that one. Lets call them one, two and three in that order. Which means (three - one) gives us the cycle count for the frame (in clock cycles) and (three - two - 4) gives us the time spent in waitvid. One last thing, in order to not spent all the time waiting in waitvid I fill the gap with a defined waitcnt to consume all those unsused cycles.

                    waitvid zero, zero
    '-----------------------------------------------
     _one_          mov     eins, cnt               ' start of frame N
    
                    mov     cnt, cnt                '
                    add     cnt, delay              '
                    waitcnt cnt, #0                 ' delay 14 + (delay - 9)
                    
    _two_           mov     zwei, cnt               ' end of frame N (sort of)
                    waitvid zero, zero
    '-----------------------------------------------
    _three_         mov     drei, cnt               ' start of frame N+1
    
    


    And here are the results:

    ' frame length = mov + (14 + (delay - 9)) + mov + waitvid
    '        delay = frame length - mov - 14 + 9 - 4 - waitvid
    '        delay = 4K*4 - 4 - 14 + 9 - 4 - 4+
    '        delay = 16371 - 4+                        expected waitvid    measured
                                    '                    cycle count      cycle count
      collect(16365)                ' -2 too early            6                6
      collect(16366)                ' -1 too early            5                5
      collect(16367)                ' +0 perfect match        4                4
      collect(16368)                ' +1 too late       16K + 4 - 1            4
      collect(16369)                ' +2 too late       16K + 4 - 2      16K + 4 - 2
    
    


    So, like it or not, the minimum cycle time for a waitvid is 4. You'll notice that the measured timing for +1 too late is also 4 (it's not a typo). In this case the frame length is not 16K cycles but 16K+1 cycles. What remains to be investigated is how that affects the next frame, i.e. whether it can be off by one as well.

    Make sure you check out other oddities listed here.
    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.mikronauts.com E-mail: mikronauts _at_ gmail _dot_ com 5.0" VGA LCD in stock!
    Morpheus dual Prop SBC w/ 512KB kit $119.95, Mem+2MB memory/IO kit $89.95, both kits $189.95 SerPlug $9.95
    Propteus and Proteus for Propeller prototyping 6.250MHz custom Crystals run Propellers at 100MHz
    Las - Large model assembler Largos - upcoming nano operating system
  • Andrey DemenevAndrey Demenev Posts: 377
    edited 2010-08-04 02:43
    kuroneko said...
    Also, the frame timing can be off by one cycle if pushed slightly too far. See this thread about waitvid timing. Which suggests that the h/w is slightly more complicated [noparse];)[/noparse]
    This may also suggest it is actually a bit simpler [noparse]:)[/noparse] Seriously - this is just the matter of how waitvid is synced with instructions execution. We can observe this "4 cycle waitvid" behavior only under certain conditions (integer PLL to system clock ratio). If for now we just think waitvid is 5 cycles minimum when generating video - we would be safe. But for sure this is interesting for things other than video (hi-speed communication maybe)
  • kuronekokuroneko Posts: 3,623
    edited 2010-08-04 03:22
    Andrey Demenev said...
    We can observe this "4 cycle waitvid" behavior only under certain conditions (integer PLL to system clock ratio).
    Do you have proof or are you just guessing? [noparse]:)[/noparse] Regardless, can you suggest a non-integer ratio so I can run a test?
  • Andrey DemenevAndrey Demenev Posts: 377
    edited 2010-08-04 04:34
    The problem with your test is that you always issue waitvids at certain time related to PLL startup. If you set FRQA to certain not round value, and perform a random delay before waitvid, you'll see that even with same ccnt waitvid cycles is not always 4 - that's due the fact that waitvid is started at some random phase of PLL, and Fpll/Fclk is not integer

    CON
      _clkmode = XTAL1|PLL8X
      _xinfreq = 12_000_000
    
    OBJ
      serial: "FullDuplexSerial"
    
    var
      long seed
    PUB main|i
    
    
      seed := 10000
      waitcnt(clkfreq*5 + cnt)
      serial.start(31, 30, %0000, 115200)
    
      repeat i from 1 to 40
        collect(16363)
    
    PRI collect(ccnt) | storage
    
      random := ?seed & $01FF_FFFF
      storage{0} := ccnt
      cognew(@start, @storage{0})
      repeat while storage{0}
    
      serial.str(string("ccnt: "))
      serial.dec(ccnt)
      serial.str(string(" frame: "))
      serial.dec(storage)
      serial.str(string(" insn: "))
      serial.dec(storage)
      serial.tx(13)
      
    CON
      zero = $1F0
      
    DAT             org     0
    
    start
                    movi    ctra, #%0_00001_101     ' PLL, VCO/4
                    mov     frqa, cfrqa
                    'movi    frqa, #%0001_00000      ' 5MHz * 16 / 4 = 20MHz
                    movi    vcfg, #%0_01_000_000
    
                    mov     delay, cnt
                    add     delay, random
                    waitcnt delay, #0
                    rdlong  delay, par
                    
                    waitvid zero, zero
                    waitvid zero, zero
    '-----------------------------------------------
                    mov     eins, cnt               ' start of frame N
    
                    mov     cnt, cnt                '
                    add     cnt, delay              '
                    waitcnt cnt, #0                 ' delay 14 + (delay - 9)
                    
                    mov     zwei, cnt               ' end of frame N (sort of)
                    waitvid zero, zero
    '-----------------------------------------------
                    mov     drei, cnt               ' start of frame N+1
    
                    neg     eins, eins
                    add     eins, drei              ' frame cycle duration
    
                    sub     drei, zwei
                    sub     drei, #4                ' waitvid cycle duration
                    
                    mov     zwei, par               ' @storage[noparse][[/noparse]0]
                    add     zwei, #4                ' @storage
                    wrlong  eins, zwei              ' store frame length
                    add     zwei, #4                ' @storage
                    wrlong  drei, zwei              ' store insn length
    
                    wrlong  zero, par               ' mark result ready
                    
                    cogid   cnt
                    cogstop cnt
    
    cfrqa           long    %0001_00000_00000_010000000_000010001
    random          long    0
    
    eins            res     1
    zwei            res     1
    drei            res     1
    
    delay           res     1
                    fit
    
    
    



    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16381 insn: [b]5[/b]
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16381 insn: [b]5[/b]
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16381 insn: [b]5[/b]
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    ccnt: 16363 frame: 16380 insn: 4
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2010-08-04 04:47
    Andrey Demenev said...
    The problem with your test is that you always issue waitvids at certain time related to PLL startup. If you set FRQA to certain not round value, and perform a random delay before waitvid, you'll see that even with same ccnt waitvid cycles is not always 4 - that's due the fact that waitvid is started at some random phase of PLL, and Fpll/Fclk is not integer
    Point taken and I agree that this behaviour is to be expected as you have to get the waitvid unblock signal sync'd with instruction execution (as you mentioned already). But that wasn't the point of the exercise. Fact is that the minimum timing (contrary to what the datasheet says) is 4, not 5. But for common usage (i.e. video) that's probably not too relevant.

    Having thought about this, the extra cycle for the frame length is probably only visible in PASM land (as it has to be sync'd to the system clock). The video h/w may well show exact frame timing.

    Post Edited (kuroneko) : 8/4/2010 4:52:21 AM GMT
  • ericballericball Posts: 774
    edited 2010-08-04 17:43
    Actually, I found the opposite when testing out my OnePinTVText driver. If I cranked up the PLL frequency so the WAITVID loop assumed WAITVID required 5 cycles I would get "sparkles" where the frame timer expired just before WAITVID had loaded the data onto the D&S buses. Backing off just slightly (WAITVID=6 cycles) would produce a stable result.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Composite NTSC sprite driver: Forum
    NTSC & PAL driver templates: ObEx Forum
    OnePinTVText driver: ObEx Forum
Sign In or Register to comment.