Phil Pilgrim (PhiPi)
01-21-2009, 06:15 AM
Here's a video gotcha I learned the hard way. I was wanting to start a video output sequence a certain amount of time after an external stimulus. It was also necessary for the video scale (vscl) to vary from event to event (think double-wide characters) but for the start time to remain invariant. In most apps, once the video hardware is started, it just keeps running, and you don't have to worry too much about any startup glitches or which of vcfg or vscl gets loaded first. The system quickly reaches a steady state, and you can just start feeding it pixels.
But I wanted to be able to turn the video on and off at precise times, so what happens at startup was of paramount importance. It seemed reasonable to assume that I could load vscl first with the scale factor I wanted, then load vcfg with the proper configuration data and that the video would start up with the scale factor I had selected. Then, once the video output was done, I could just set vcfg to zero and wait for the next event. I couldn't have been more wrong! The startup delays varied, and I couldn't figure out why.
What I learned and the take-home lesson from this thread is as follows: The video hardware does not load its internal scaling register from vscl when vcfg is initialized. The only time this register is loaded is during the execution of a waitvid. When you turn on the video by setting vcfg, it starts up using the scaling values extant internally, not the value in vscl. What this means is that you have to "prime the pump" with the next vscl value before the last waitvid. The last waitvid can, however, be a dummy. In other words, you can set vcfg to zero immediately following it, thus truncating the video output from it almost instantly.
Here's a program I wrote to illustrate what I'm talking about:
CON
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000
CLKSPERPIXEL = 1
PUB Start
cognew(@synctest,0)
DAT
org 0
synctest mov ctra,ctra0 'Set up ctra for video PLL.
mov frqa,frqa0
mov vscl,vscl0 'Set up video scaling.
mov vcfg,#0 'Disable video output for now.
mov dira,#1
:testlp or outa,#1 'Wide marker.
nop
nop
andn outa,#1
mov vscl,vscl0 'Setup fast video scale.
mov vcfg,vcfg0 'Enable video output.
waitvid colors,pixels 'Output video high.
waitvid colors,#0 'Output video low.
mov vcfg,#0 'Disable video output before low finishes.
or outa,#1 'Narrow marker.
andn outa,#1
mov vscl,vscl1 'Setup slow video scale.
mov vcfg,vcfg0 'Enable video output.
waitvid colors,pixels 'Output video high.
mov vscl,vscl0 '<------------EXTRA VSCL LOAD-------------<
waitvid colors,#0 'Output video low.
mov vcfg,#0 'Turn off video output.
jmp #:testlp 'Loop-d-loop.
ctra0 long %00001 << 26 | (%011 + >| CLKSPERPIXEL) << 23
frqa0 long $16e8_b9fd
vscl0 long CLKSPERPIXEL << 12 | 16 * CLKSPERPIXEL
vscl1 long CLKSPERPIXEL << 13 | 32 * CLKSPERPIXEL
vcfg0 long %01 << 29 | 1 << 28 | %000 << 9 | %0001
colors long $0101_0100
pixels long $ffff_ffff
It generates two video frames, one after each marker pulse: a narrow one, followed by a wide one. When the "extra vscl load" is commented out, this is what the output looks like:
········http://forums.parallax.com/attachment.php?attachmentid=58118
Notice that the start time is one full video frame long, equal in length to the frame before the video was turned off.
Now, with the extra load included, here's the improved output:
········http://forums.parallax.com/attachment.php?attachmentid=58119
Here, the start time is always one full narrow video frame, since this is the scaling written with the extra load. For an even faster startup, one could load vscl at the end of every line of video with an even smaller clocks-per-frame value.
-Phil
_
But I wanted to be able to turn the video on and off at precise times, so what happens at startup was of paramount importance. It seemed reasonable to assume that I could load vscl first with the scale factor I wanted, then load vcfg with the proper configuration data and that the video would start up with the scale factor I had selected. Then, once the video output was done, I could just set vcfg to zero and wait for the next event. I couldn't have been more wrong! The startup delays varied, and I couldn't figure out why.
What I learned and the take-home lesson from this thread is as follows: The video hardware does not load its internal scaling register from vscl when vcfg is initialized. The only time this register is loaded is during the execution of a waitvid. When you turn on the video by setting vcfg, it starts up using the scaling values extant internally, not the value in vscl. What this means is that you have to "prime the pump" with the next vscl value before the last waitvid. The last waitvid can, however, be a dummy. In other words, you can set vcfg to zero immediately following it, thus truncating the video output from it almost instantly.
Here's a program I wrote to illustrate what I'm talking about:
CON
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000
CLKSPERPIXEL = 1
PUB Start
cognew(@synctest,0)
DAT
org 0
synctest mov ctra,ctra0 'Set up ctra for video PLL.
mov frqa,frqa0
mov vscl,vscl0 'Set up video scaling.
mov vcfg,#0 'Disable video output for now.
mov dira,#1
:testlp or outa,#1 'Wide marker.
nop
nop
andn outa,#1
mov vscl,vscl0 'Setup fast video scale.
mov vcfg,vcfg0 'Enable video output.
waitvid colors,pixels 'Output video high.
waitvid colors,#0 'Output video low.
mov vcfg,#0 'Disable video output before low finishes.
or outa,#1 'Narrow marker.
andn outa,#1
mov vscl,vscl1 'Setup slow video scale.
mov vcfg,vcfg0 'Enable video output.
waitvid colors,pixels 'Output video high.
mov vscl,vscl0 '<------------EXTRA VSCL LOAD-------------<
waitvid colors,#0 'Output video low.
mov vcfg,#0 'Turn off video output.
jmp #:testlp 'Loop-d-loop.
ctra0 long %00001 << 26 | (%011 + >| CLKSPERPIXEL) << 23
frqa0 long $16e8_b9fd
vscl0 long CLKSPERPIXEL << 12 | 16 * CLKSPERPIXEL
vscl1 long CLKSPERPIXEL << 13 | 32 * CLKSPERPIXEL
vcfg0 long %01 << 29 | 1 << 28 | %000 << 9 | %0001
colors long $0101_0100
pixels long $ffff_ffff
It generates two video frames, one after each marker pulse: a narrow one, followed by a wide one. When the "extra vscl load" is commented out, this is what the output looks like:
········http://forums.parallax.com/attachment.php?attachmentid=58118
Notice that the start time is one full video frame long, equal in length to the frame before the video was turned off.
Now, with the extra load included, here's the improved output:
········http://forums.parallax.com/attachment.php?attachmentid=58119
Here, the start time is always one full narrow video frame, since this is the scaling written with the extra load. For an even faster startup, one could load vscl at the end of every line of video with an even smaller clocks-per-frame value.
-Phil
_