Wrapping my head around Video Generator issues
localroger
Posts: 3,452
I got pulled off of Windmill for a bit to do some small stuff that requires VGA support, so while I'm in video driver mode I figure I should figure out how the video generator works for real. I still don't feel confident enough to just start from scratch and write a driver.
I pretty much get how to use FRQA to set up a dot clock and use WAITVID to farm out colors and pixels. What is puzzling me is exactly what is possible for making the other timing, some of which can be very tricky, for sync and front and back porches and so on.
I understand that the VSCL FrameClocks parameter is used by some of the drivers out there to generate various random time delays, but what I don't understand about it is this:
When you execute a WAITVID the color and pixel maps you supply are written to the staging registers so that when the last WAITVID finishes, they will be moved to the shift registers and start going out. But say you want to send out N clocks of some fixed pattern to generate a sync pulse. You need to also change FrameClocks to do that.
By my reading of the docs, it seems that if you issue a WAITVID, then change VSCL, your change will affect the current ongoing WAITVID whose end your new WAITVID will be WAITing for.
I notice that a lot of the public code issues WAITVID, then immediately sets VSCL appropriately. Can someone explain to me exactly how this works?
I pretty much get how to use FRQA to set up a dot clock and use WAITVID to farm out colors and pixels. What is puzzling me is exactly what is possible for making the other timing, some of which can be very tricky, for sync and front and back porches and so on.
I understand that the VSCL FrameClocks parameter is used by some of the drivers out there to generate various random time delays, but what I don't understand about it is this:
When you execute a WAITVID the color and pixel maps you supply are written to the staging registers so that when the last WAITVID finishes, they will be moved to the shift registers and start going out. But say you want to send out N clocks of some fixed pattern to generate a sync pulse. You need to also change FrameClocks to do that.
By my reading of the docs, it seems that if you issue a WAITVID, then change VSCL, your change will affect the current ongoing WAITVID whose end your new WAITVID will be WAITing for.
I notice that a lot of the public code issues WAITVID, then immediately sets VSCL appropriately. Can someone explain to me exactly how this works?
Comments
BTW, the use of the internal source and destination data busses for holding the data is the reason you can't simply repeat a waitvid by ignoring the next "appointment". If you do, the video circuitry just grabs whatever happens to be on those busses from the instruction currently being executed, resulting in garbage output. I'm told that, in the Prop 2, these data will be buffered in their own registers.
-Phil
VSCL and the pixels and colors are all buffered. VSCL contains 0 on first waitvid, so there is a 4096 PLLA setup time, after that you will have specified the parameters for the upcoming frame, during the frame you are on. Generally speaking, start one, do your setup for the signal during that time, then as each frame is pushing pixels, you take that time to setup the next frame, and on it goes..
There are things about VCFG that are not buffered however. It's possible to change the output pin mid frame, for example.
Set VCFG to 0 to shut it all off. (I don't often do this, and believe it just stops, but it might finish the frame.)
One thing I've had the occasional trouble with is switching from 2 color to 4 color mode. There is a small time window where if you do this too close to the next frame, it botches that frame, not transitioning properly. Had it come up on Potatotext. Some shuffling of instructions made it go away. At that time I should have captured it, but was really working hard to get that one running...
I personally like to have the registers set long before the frame is up to avoid that condition.
Pre-calculate your sync values, and choose a PLLA that makes sense for all of that, and round to the nearest PLLA"pixel" for sync. There have been lots of ways to do sync. If you are on TV, check out Eric's antics! He's done a lot of interesting and varied ways to make the NTSC signal, including the latest Apple ][ double high res mode, which I'm taking apart to learn right now. If you are on VGA, it's somewhat easier to get the signal all done, though the sweep frequency is higher, forcing tighter loops, and lower resolutions at higher color depths. Anyway, once you've calculated your sync, generally you can just stuff the frame data in, along with "pixels" that will do the job nicely with no worries about the current frame in progress.
What I've done, and continue to do is trace through a driver, reproducing the calcs, then test to find out where the variability is in the active display. Once you know how many PLLA that active part is, and what the front and back porch values are, then you are free to play with the three of those, doing most anything you want to, leaving the rest of the signal alone.
I've a scope now, which makes getting everything going easier, but I didn't at first. In that scenario, I find it best to build "color bar" or "checker board" or "bitmap" code from a existing driver framework, then do timing tests to determine what's possible, then build the graphics loops needed from there. It's also helpful to refactor a driver, like say, consolidate it from a big loop, to a few calls, just to understand all the parts.
The Parallax drivers Chip wrote are complex, and they do a LOT. It's also easier, IMHO, to just start with a driver that's more fixed in it's behavior, then making one change at a time, bend it to the task at hand. This is easier with say a Kye VGA, or Eric TV driver than it will be the Parallax ones. I like the Parallax ones a lot though, it's just a lot to take in to get started on driver writing, that's all.