jazzed inspired NTSC/PAL Driver.
davidsaunders
Posts: 1,559
jazzed challenged me to make a full color video driver for output to television using the Propeller Platform (by: Gadget Gangster) SDRAM module for the frame buffer and video output. Giving the conditions that it must exceed the current drivers in display capability, to the point of being able to not having to repeat any pattern in order to fill the display and it must use 5 COGS or less.
And I accepted his challenge. I am going to order the SDRAM module as soon as I can afford it. In the mean time I will be using a SDRAM IC scavenged from an old DIMM to get started (to which I had already soldered leads to breadboard it for another project, that is long since done). I am also looking through all my old hardware to find the appropriate resistors for the video out. Hopefully the IC on the SDRAM module is close enough that I will not have to make major modifications in order to use my code on the correct HW.
So as to keep the number of posts I have decided to post a periodic log of the status of the progress I am making with this project. and here it is:
And I accepted his challenge. I am going to order the SDRAM module as soon as I can afford it. In the mean time I will be using a SDRAM IC scavenged from an old DIMM to get started (to which I had already soldered leads to breadboard it for another project, that is long since done). I am also looking through all my old hardware to find the appropriate resistors for the video out. Hopefully the IC on the SDRAM module is close enough that I will not have to make major modifications in order to use my code on the correct HW.
So as to keep the number of posts I have decided to post a periodic log of the status of the progress I am making with this project. and here it is:
3/23/2011 1:) Pixel and simple line drawing functions implemented. Up to 2000 vector draw commands per frame, though in some cases as few as 150 (figure aprox 2000 pixels updated by vector drawing per frame). 2:) Still trying to get the output timing lined up for NTSC video. This part may take a while. 3/23/2011 Wow what a day. I have not accomplished this much in a single day in a while. Today I accomplished the fallowing: 1:) Accepted the challenge to code a better TV video driver for the Propeller Platform using external SDRAM. 2:) Managed to get a SDRAM driver working on the Propeller, that is based on an earlier, unreleased driver that I had written for the AVR. 3:) Got the SDRAM read and write speed up to about 4700000 bytes per second max. This is fast enough for this application. 4:) Began refreshing my knowledge of NTSC, and began studying PAL in relation to NTSC.
Comments
I think it's great that you accept the challenge. Video on Propeller has made some nice advances in the last 12 months and if you can get something like this working by UPEW end of May, then we will all have something to celebrate in Rocklin.
No pressure though. We'll all be happy to enjoy your contribution whenever it's done.
http://forums.parallax.com/showthread.php?126813-Video-timing-New-discoveries-improved-synchronisation-code.
Hope that helps.
--trodoss
Thank you kurenko.
This is in one of the links i posted for you in the other thread. SdramTest-8bit
Some information on the progress:
The Video driver will use COGS 7 and 6 (at this point), and the hub mem used for parameters and buffers is defined by the following addresses:
sdrcmd = $77C0
sdrhub = $77C4
sdraddr = $77C8
drawbuff = $77D0
viddat = $7BD4
vidcmd = $7BD4
vidpar0 = $7BD8
vidpar1 = $7BDC
vidpar2 = $7BE0
vidpar3 = $7BE4
vidxsz = $7BE8
vidysz = $7BEC
linebuff = $7BF0
inbuff = $7BF0
outbuff = $7DF0
The details of the commands is still somewhat in limbo.
If at all possible, the SDRAM should serve as both a video buffer and a program code/data store. I suppose one could use 32MB for video buffers only. One thing at a time is fine.
Hardcoded addresses for each of your variables is probably a mistake. Create a "DAT structure" that can live anywhere in memory and be passed to your driver by reference.
Unfortunately a driver requiring 6 or 7 COGs will probably not get used. Maybe that can be optimized later.
DavidSaunders, do not use coginit to start your cogs! It's very bad programming practice. Use cognew, and record the cog number that's returned, in case you need to stop the cog later.
-Phil
Cogs 6 & 7, only constitute 2 out of the cogs available in a Propeller. As to the thought on not using static locations; Is there a way to make sure that DAT locations are as close to the top of mem as possible? I ask this because the reason for this choice is to make sure that everything is as much out of the way as possible, as most of the code that I have taken the time to look at only uses the lower addresses, and I wish to make it simple to overwrite the contents of hub ram for applications that would benefit from doing so. Also the buffers are just the default locations, the command and parameter stores are the only portion limited to the static address range.
Done. Now the CogInit statements are replaced with CogNew. There were only 3 of them total.
A driver that exists in the COG, can just be loaded when needed, or compiled in to the HUB, perhaps in a buffer region, and any number of things.
There really should be no assumptions, other than those needed to make the driver work, such as memory needing LONG, or WORD alignment, etc...
Letting the compiler set the addresses using a "DAT structure" is much better practice. DAT generates a "global" block within the code segment of a program. If you need to reference the block from high memory for some reason that's easy enough. The driver by definition will be singleton, so it doesn't matter if it's global or not.
Interestingly, I think it's easier to use the compiler, freeing upper memory, which it won't touch. Build from the bottom and let it do what it does. Your DAT can be at the end, and then you can rather easily call out absolute addresses in higher memory as you see fit. The Parallax drivers do this, taking advantage of the bottom up approach of the compiler.
From there, assuming a HUB memory model, it's easy to just deal with buffers as addresses.
Since this is external memory, to a degree, some of that might not make sense, depending on what it is you want your driver to do, of course.
I would say that it's not bad practice, but advanced technique. For example if you need 2 or 4 cogs with interleaved access to hub memory
Since object references can not be passed in spin (a good aspect of spin in some ways), such singletons are necessary for any object to have access to a display or serial console. Of course this can be a problem if many objects try to access the same resource simultaneously in a stream, but that is manageable by spin-locks or programmer discipline.
Wikipedia has a page dedicated to the singleton. Read the first paragraph.
The coginit has a place in some code as Andrey mentions, it is rarely necessary though. Phil is just trying to help people stay out of trouble. Let's not argue about it here.
I did put a note in the main spin source stating that these need to be loaded in consecutive COGS and as such to make sure that the first two available COGS are consecutive and that no cogs are started between the two. And this morning I made an optimization that voids that. It is now best for them to be separated by three cogs each direction, being for example in COG 7 and COG 3, or 6 and 2, etc...
Thank you again for your challenge. This is very good for me, as my "Day Job" is the creation of the MultiDB68K (backed by an investor that wishes to remain a silent partner), an Amiga clone that uses Propellers to simulate the custom HW. For more info on that you can check out: http://davidsaunders.cwahi.net/MultiDB68K/index.html.
By the way if any has any suggestions for a better name than MultiDB68K, we are still in need of a better name.
-Phil
Ok here we go: Take a situation were one COG has to send a request to the other, and the other has to respond and the timing has to be very predictable; beings that the current function of the two COGS changes every scan line this can not be done if the distance between the two COGs HUB access window (in the forward direction) is not equal. And coding two different versions to handle the difference would require that the distance for each be a constant (as computing it at init would take extra code, that would have to be overwritten later in order to make space for the driver code), and a bit of extra work.