Video squashed sprite
Bocephus
Posts: 58
I'm studying how to make video and I have generated top, center, and bottom scans with different colors. I decided to make a simple stick man sprite and attempt to introduce it into the scans. It worked somewhat as expected since the stick man is clearly in the video but the sprite is short and squatty.
How do I make the sprite stay at 16x16?
Also, how would I make a 16x16 sprite take up a larger area? Such as in my code below in the center_scanlines section, where there would be 144 lines available to scale the sprite over.
How do I make the sprite stay at 16x16?
Also, how would I make a 16x16 sprite take up a larger area? Such as in my code below in the center_scanlines section, where there would be 144 lines available to scale the sprite over.
Next_Frame ' video loop mov r1, #60 ' 262-18 = 244 available :top_scanlines mov vscl, clkperpixel8_clkperframe12 waitvid color_index, hsync_pixels mov vscl, active_vid_values waitvid color_blue, pixel_pattern djnz r1, #:top_scanlines mov r1, #128 :center_scanlines mov vscl, clkperpixel8_clkperframe12 waitvid color_index, hsync_pixels mov vscl, active_vid_values waitvid color_white, pixel_pattern djnz r1, #:center_scanlines ' ========== man bitmap ========== mov r1, #16 mov index, #man_bitmap :man_scanlines mov vscl, clkperpixel8_clkperframe12 waitvid color_index, hsync_pixels movs :show_man,index mov vscl, active_vid_values :show_man waitvid man_palette_map, 0-0 add index, #1 djnz r1, #:man_scanlines ' ================================ mov r1, #40 :bottom_scanlines mov vscl, clkperpixel8_clkperframe12 waitvid color_index, hsync_pixels mov vscl, active_vid_values waitvid color_green, pixel_pattern djnz r1, #:bottom_scanlines call #Vsync_High call #Vsync_Low call #Vsync_High jmp #Next_Frame ' end video loop
Comments
In the horizontal direction, your VCSL can control the size of the "pixels". You will need to figure out how you want to do your active pixel area timing, in terms of PLLA cycles / scan line.
In the vertical direction, you will need to duplicate your sprite data, either one scan, two scans, etc... high to get scaling in that direction.
Make each pixel a unique, contrasting color, and write the sprite to the display. If all the pixels can actually be seen, then you have a scaling matter, meaning you need to manage your pixel timing horizontally to get your aspect ratio closer to what you are envisioning.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
I'll read some more about this tonight and have another go at it.
For NTSC video, each scan line is a multiple of the PLLA, and the PLLA is derived from the colorburst. There is the sync area, which is always the same timing. The rest can vary.
The key here is to calculate how many PLLA cycles you have on the scanline.
Subtract those cycles needed for the sync.
Then you determine what your porch size is, and the porch is the overscan border, just for reference. Subtract those, leaving you with your active video area cycles. The active video area is also known as the safe area. On older computers, this is "the graphics screen" with the porches being "the border".
I like to use 2560 cycles for this area because it maps perfectly to the color cycle, and provides common, meaningful resolutions in the active area.
The key for exploring this is to get everything setup so that you can vary the pixel timings in the active area. I find it handy to have a few different loops.
There is the frame loop, and this one just runs over and over, for a non-interlaced display. If you are doing interlace, that loop runs as two different states, one for the even frame, one for the odd frame. For starting out, I would ignore this, just doing non-interlaced video.
Inside the frame loop, you've got:
VSYNC
Top border, consisting of blank scanlines, drawn at color $02. These are just two waitvids. One for the HSYNC pulse, and one more to draw the whole scanline blank. The PLLA cycle count of these two waitvids needs to equal your PLLA / scanline.
When the top border is done, you enter the first line of the active area. This consists of the same HSYNC waitvid, a shorter border waitvid done exactly the same way the blank scan line was done, just shorter to consume the PLLA cycles for your border.
Then you have a loop! This is your graphics loop. What this loop does is fetch pixels from the display buffer, load the waitvid, then repeat for as many pixels as you have in the active area.
Finish off with your other border, on the right, done the same way the other border is done.
To change waitvid timing, you do this just prior to executing the next waitvid. The waitvid currently running, won't generally be impacted by a VSCL change, leaving you time to get the next waitvid setup.
Once started, you keep waitvids running, only changing the timing of them to get the various parts of the screen done.
Let's say your active area is 2560 PLLA. Here is how it all breaks down.
Before I do that, know that waitvids operate either one bit per pixel, two bits per pixel, or 8 bits per pixel, with a trick where the colors are actually pixels, and you use the waitvid in reverse from how you use it at one and two bits per pixel.
For one and two bits per pixel, the waitvid is "waitvid colors, pixels" where the colors long has the four color definitions, one byte per color, and pixels is the actual bit pattern drawn to the screen.
For 8 bits per pixel, and only about 80-130 of the colors are actually useful, the waitvid is "waitvid colors, #%3210" What that does is define 4 pixels, one of each color, transforming the colors long into just pixels! You can find examples of this sprinkled throughout many video drivers.
Ok then, now it's time to figure out the frame.
Let's say one bit per pixel is being used. Since pixels is a long, that means you get up to 32 pixels per waitvid! Let's say it's 32, and calculate.
For a 160 pixel screen, we first get the number of waitvids needed. That's 160/32 = 5 waitvids. Your active graphics loop will execute 5 times then.
Now we figure out the VSCL. There are two numbers needed.
PLLA per pixel = 2560 PLLA per active scanline / 160 pixels = 16 PLLA per pixel.
Now we figure out the size of the waitvid frame, which is the total number of pixels to be output per frame. That's 16x32 = 512 PLLA per waitvid.
Now you take the info, put it into a VSCL, and execute it just prior to entering into your active pixel loop. When your active pixel loop ends, you load another VSCL to set the timing for the border.
A 2 bit per pixel screen means 16 pixels per waitvid max. so then:
2560 / 160 = 16 PLLA / pixel, nothing changes here.
16 x 16 = 256 PLLA / waitvid = 10 waitvids, so the math checks out perfectly.
If one bit per pixel is 5 waitvids, then two bits will be 10 waitvids per active scanline.
Now, 8 bits per pixel mode means only 4 pixels per waitvid, so that's
16x4 = 64 PLLA / waitvid frame.
2560 / 64 = 40 waitvids, each fetching 4 bytes = 160 pixels or 160 bytes.
Now you can see as the data rate goes up, you have less and less free cycles to run your active pixel loop, and this is the dynamic of propeller resolution, bits per pixel, clock speed and HUB - COG memory interaction plays out.
One more example then, let's choose a 320 pixel display, 2 bits per pixel, for a 320 pixel 4 color display.
2560 / 320 = 8 PLLA per pixel.
Note that a minimum of 16 PLLA per pixel is required for the propeller to output a full color display. Anything less than that will overdrive the color, resulting in artifacting. This can be a good thing as my wiki entry shows here:
propeller.wikispaces.com/Colors
...but can be a bad thing depending on how you code your video signal. That's a topic for another day though, just know this is true for now.
So then, 2 bits per pixel means 16 pixels per waitvid max, so we divide
320 pixels / 16 = 20 waitvids being necessary per active scan line.
Finally, the waitvid frame = 8 * 16 = 128 PLLA per waitvid.
These calculations can be seen in the potatotext driver, linked in my sig.
Eric Ball wrote up some nice NTSC templates you can use to build a simple bitmap screen. Search his posts and you will find it. I don't have the link handy at the moment. That's what I would do starting out as bitmaps require the least code, and are easy to setup test data cases for. Once you get a bitmap running, and have good control over resolution, color, borders, etc... you then can start to work on sprites, tiles and other things.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 1/22/2010 7:53:16 PM GMT
I am trying to implement a Vwait in a 2-color text driver (similar to some of your first 8x8 drivers) and ran into a snag.·
I tried putting the Vwait after the frame draw loop, but it does not seem to work quite like I had thought it would.
Is it something easy that I am missing?
Thanks,
--trodoss
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Game(s) Mythic Flight (0.9)
Utilities Font Editors (AIGeneric, Potato_Text, etc.)
Bocephus: Cool. Just walk it through, one step at a time. Remember to think your scan line through, and make changes that can be seen, and life goes much better in video land.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Go ahead and post some code, if you want to.
Here is what needs to happen for a VBLANK flag. There are two approaches.
1. Have the TV driver write it's blanking status to the HUB.
2. Have the TV driver write it's draw status to the HUB, only.
For both approaches, what you need to do is establish a HUB address to hold the data, and make sure both the TV driver and your parent SPIN program have access to it. Easiest way to do this is to include it in your stack of variables, whose address is passed to the TV cog, when started.
From the parent SPIN program, containing that parameter block, you reference it with @VBLANK. In the TV COG, you need to capture it's address, then store that address in a long for use with a wrlong instruction or two. That can look like this:
In your parameter block, you've got this in a DAT zone:
DAT
x_pixels -- long 160
y_pixels -- long 192
screen -- @screen_buffer
VBLANK -- long 0
When the SPIN program that calls the TV COG wants to read the flag, it's just @VBLANK, which will point right to the DAT. In the TV COG, you would do this:
mov Address, PAR
rdlong cog_x_pixelvalue, Address
add Address, #4
rdlong cog_y_pixelvalue, Address
add Address, #4
rdlong cog_screen, Address
***add Address, #4
***mov cog_VBLANK, Address.
In the COG dat, it's handy to have constants:
one -- long 1
zero -- long 0
Note the last two lines are actually writing the address to the COG, so it can be used like this:
wrlong one, cog_VBLANK
Be really sure you understand that. When you save a pointer to an address, you generally use MOV because the address is being captured in a COG long, so you can write to it later on. When you save a value, you use a rdlong, so that you fetch what is at that address! (I got hosed on this multiple times)
Once you get all that done, you can write values to the HUB, to be acted upon by the higher level COG that needs to interact with the TV cog.
In your video code, you put a "wrlong one, cog_VBLANK" at the end of your graphics frame. This is right after you've drawn the last scan line with graphics on it, thus indicating that you are in the blanking period. It's not exactly VBLANK, but it's great because the TV beam is done, meaning you can change stuff with no worries, and that's the point of it, so that's where I would put it.
You do a "wrlong zero, cog_VBLANK" right as you start drawing graphics scan lines. This means the TV beam is painting a picture, so it's best to NOT make changes, or flicker will be seen.
That's approach number one, and is used in some of my older drivers, and the ones Andre' included with HYDRA.
Approach number 2 is all about writes from the TV cog, and reads and writes in the higher level cog, and is the approach used in the new 8x8 driver code.
In this scenario, the TV COG writes a one, when the scan lines start, and that's it! For an interlaced display, either a one or a two is written, depending on even or odd frame. That's needed because the two frames are different. So, let's assume non-interlaced display then.
A simple "wrlong one, cog_VBLANK", right as the graphics start indicates the display is no longer blanking, and is actually drawing.
The higher level COG writes a zero, then waits for it to transition to a one, just to sync up with the display. Then it writes another zero, then does it's drawing while checking the VBLANK flag address. It keeps drawing, until it sees the one placed there by the TV COG, at which point it sees that, stops to sync up, then writes it's zero again.
The second method is good for multiple cogs making a display. The first one is fine for most things.
Really, the first method is all about the TV cog controlling everything. Other cogs just see the flags and do stuff. This is the easiest way.
The second method causes a handshake to occur as the resetting of the flag happens in one cog, and the setting of it happens in another COG. More complex, but necessary in most instances of multi-cog drivers. That took me a long while to grok too. (I had to go peek at other drivers!)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 1/27/2010 12:07:42 AM GMT
In a single buffer scenario, where you are using the flag to prevent screen artifacts, really, you've got to clear the whole screen, then draw everything before the graphics start.
And if you don't have time, then you have to have logic so that the movement of things is spread out over multiple frames, and or to leave some of the display static (don't clear whole screen), or limit that which is seen each frame.
Not sure which problems you have, but we can talk about them! Maybe others will jump in too.
Oh, and don't get frustrated over that. Know what I'm frustrated over? Fricking simple game logic in FREEWAY. I can make a video driver sing, but I can't seem to get simple game states sorted, LOL!!
So, you will probably see me asking for some more hints here in the near future. Funny how this stuff works. [noparse]:)[/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
The pointer -vs- address part, I wrote on above, is the problem.
In one of your programs, you need to setup a DAT for your shared variable, then communicate it to the other programs. I would put it in your LinkDemo_TV_Text_001 program.
Communicate it to both the Linkdemo_001, and LinkDemo_TV_001 programs.
For Linkdemo_001, you need to add a method in LinkDemo_TV_Text_001 to pass the pointer as a returned value. That looks like this:
What that does is return the address of the VBLANK location in the HUB for the DAT variable to be shared.
From Linkdemo_001, just call it like this:
VBLANK_address := Text.GetPtrToVblank
Now you have the address in the Hub stored in the variable VBLANK_address. Use VBLANK_address to tell SPIN where to get the data to wait on.
Going the other way, communicate it to the Linkdemo_TV_001, using the address from the PAR register, like I wrote above. You have a rdlong instead of a mov. That will get the contents of whatever the address points to, not the address!!
Now VSyncPtr and the variable you use in your top level linkdemo_001 will contain the same VALUE, which is a POINTER, or ADDRESS to a specific HUB memory location.
When the TV COG writes it, the top level program can read it.
I might have time for more later, but that is a start. In your Linkdemo_001, you've got a Vwait procedure that needs to actually read the VblankPtr, not set a value. I don't have a prop hooked up, so I'll just tell you that. Can't run stuff at the moment [noparse]:([/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Thanks!
Pointer vs address...should have known! I have run into that before in just Spin code.
I will try the code changes mentioned and see how it goes.
Technically I could solve timing issues by going with a double buffer approach (like I did for the Mythic Flight code). One of these days I need to post my VCS: Joust code. That one was pretty fun, but much thanks goes to Baggers (who did all the hard work).
I was trying to see if I could avoid the space required for "double buffering," since I will be, in effect packing as much "game" as I can into the Prop's limited resources that are left. Should be doable hopefully, since it has been done in Bagger's work. Granted, I am no Baggers [noparse];)[/noparse] May require turning it into a "multicog" driver though (to handle the rendering of scanlines, like the new Potato_Text driver). A lot of that...still figuring out, but I understand the "how" much better.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Game(s) Mythic Flight (0.9)
Utilities Font Editors (AIGeneric, Potato_Text, etc.)
Not a lot can be done with one COG. A look at my currently failed KABOOM project will show you the limits there. It's a single COG dynamic display, and it can't quite do that game. That's two sprites per line.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Looking at the code though I think I now see how you were using the VBLANK in KABOOM_TV_18. I might give that a try and see how it works (just passing the value 1-way).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Game(s) Mythic Flight (0.9)
Utilities Font Editors (AIGeneric, Potato_Text, etc.)
I have a version that works better, but it looks like I will have to work on the rendering.· It is a little too slow to render the background, then draw the character on top.
Thanks for the help!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Game(s) Mythic Flight (0.9)
Utilities Font Editors (AIGeneric, Potato_Text, etc.)
Yeah, I should have thought quick how the Vblank worked on that one. It's right where you want to be. Cool. Would have saved some typing.
I've learned lots of new stuff, meaning I think that one could work for me now. Frankly, I think one COG can do those graphics. There are much better ways to do things. When I get through fighting myself on FREEWAY, I've got to revisit that one. Doing the Vblank that way is solid though. No worries there, just don't go down the road I did for sprites!
It's too dynamic, and wastes a lot of blanking time doing nothing, or stuff that could be done more efficiently. Still, it's a nice benchmark as to what can be done in a COG.
You should look at the VCS like driver Baggers wrote. The graphics style might not appeal to you, but his sprite renderer, and how it's got the Vblank stuff setup is very good. It can operate all the way down to 2 COGs, and do quite a bit with those COGs. In video, going from one COG to two is a huge jump. Potatotext is possible because of that, where if you look at the older 8x8 drivers, they are sweet, but have a lot of limitations.
It's key to know what is expensive and what isn't. Baggers has shown us a lot in that regard.
Color lookups are expensive as hell. That one thing is why Potatotext is a two COG deal. Where it's possible to move color lookups out of your video COG, do it. Sprite bit masking is also very expensive. So, if you need to overlay sprites with background, do it with simple bit sizes. The trade-off is more HUB memory needed for data, but then the data being possible to draw to screen with less COG effort.
Good progress! I like video projects to a fault!! So much fun to mess with the beam and timing.... [noparse]:)[/noparse] I'm glad I could help some.
@Bocephus: Hope you don't mind the video chatter on your thread... Please jump right back in anytime. Looks like we just kind of started talking here. Sorry about that.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 1/27/2010 4:39:26 PM GMT
After looking at the code trodoss posted I realize that I can't be far from making my sprite stand up correctly. My inability to solve this is driving me crazy. I will attach the code that I am using to learn this and if either of y'all have a moment maybe you will see the issue immediately. I started with the hel driver and butchered it down to the attached.
Btw, on entry why do you jump over the variables instead of placing them at the end with the others?
Are you doing things in the COG for learning purposes only?
The first thing that stuck out was having your sprite object in the COG. For an object or two, that works ok, but the reality is you need to pull your data from the HUB.
The second thing that leaps out at me is your code right now is kind of drawing a fixed object to the screen. That's a great learning pass, but will very quickly end up a dead end, as objects need to move around.
The jump over variables bit is a clever way of making quick, in COG tables without having to add an offset address. If the data is located at COG address 0, then the index can be used directly. If the data is somewhere else in the COG, then it's the index, plus the offset address, which slows the whole works down.
Frankly, once you get into index, plus offset, everything goes just as fast from the HUB as it does the COG. Also on that, you can't do much more than just do very simple displays with only the COG, meaning the sooner you start pulling data from the HUB, the better!
Does the program you have attached run as is, and are you on a HYDRA?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
I am presuming that with a single pin (1 resistor), we can only get B&W. Is there any way we could use a 2 or 3 resistor voltage divider connected to the prop pin and use tristate to get 3 states?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
· Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
Post Edited (Cluso99) : 2/8/2010 3:21:58 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
It took a lot of reading/re-reading over to see what I was missing, but I finally got it.
Thanks!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Game(s) Mythic Flight
Utilities Font Editors (AIGeneric, Potato_Text, etc.)
I'm glad it helped. Right now, I'm stuck in a do or die real work project, and just have been checking in to read the goings on.
I do believe the contributor above may be spam, however.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Wow!
I used to eat TV receiver system design and repair for LUNCH - but that was a loooong time ago. This stuff is a real wake-up call. (You should see the dust flying outta my brain!)
I just picked up a Propeller board, and when I found out it could do video - Hot Damn! - you had my interest bigtime. At the risk of potentially hijacking this thread, let me ask a couple of questions:
1. So far, I have seen much on code to actually DO the video - various demos, etc. However I have seen NOTHING about how to actually attach a Propeller to some video output device, be it a TV or a VGA monitor. I would be very surprised if it were as simple as plugging a few pins from a 15 pin VGA connector into the Propeller board's header.
2. The Propeller board I have, (P8X32A Quick Start), supposedly has one video generator per cog/core/whatever. Why? To drive more than one video output device at a time? Mux the video signals to create something awesome, (or awful? :-) )
3: (Possibly WAY off topic) I see it over and over again that the designers of the P8X32A decided that implementing interrupts was not necessary. (say WHAT?!!) However, when I see things like "wait[something]", it just gets my teeth on edge as I can think of dozens of things a cog could be doing (especially with video!) instead of standing around waiting for some event. Any idea why? Or maybe I should just go looking for a forum on the P8X32A itself?
In any event, I am going to have to read this particular forum at least several times more - AND try some of the code when I find out how to hook this thing up to a monitor! - just to begin to understand what you folks are talking about.
Again, Wow!! you guys rock!
Thanks!
Jim (JR)
p.s. Is there anyway to "report" a reply? Hopefully the admin's will clobber that blasted spam entry!
1) Look at the schematic for the Propeller Demo Board. There's a link to it on the webstore product page for it. This shows how to attach a Prop to either a TV or VGA display (or both). Essentially, you need a few resistors to create a DAC for the TV or several DACs, one for each VGA color signal. There is a 1-pin video driver that only needs a single series resistor for B&W TV.
2) The 8 cogs are identical, so each includes a video generator which is not really very sophisticated. A lot of the video generation is done in software. For large VGA text displays, a single cog isn't fast enough to fetch a line of text, convert to scan lines of pixels, then actually display the pixels. Several cogs can be synchronized so, while one cog is displaying 8 or more lines of pixels, other cogs are fetching and rendering other lines of text to be ready to swap roles for the next group of scan lines. You can also have different simultaneous displays on a TV and VGA display or two TVs. I've done this for debugging with the main display on a TV or VGA and a debug display on a TV.
3) This has been discussed ad-nauseum. The decision to not have interrupts was very deliberate and has to do mostly with making it easy to create deterministic code. Remember that a cog that's waiting for something or stopped draws almost no power. Cogs that are producing video are often very very busy and the WAITVID does not wait long. It's used more for synchronization. It's fairly easy to write code for cogs that is multitasking. The FullDuplexSerial driver for example switches between receive and transmit co-routines. There's even a 4-port serial driver that switches among receive and transmit for up to 4 separate serial ports.
Re: #3
I have been having a running discussion with Jeff Martin about a number of things, including the lack of interrupts. I sent him this analysis of the logic behind it.
On a more technical note – Re: our discussion about interrupts.
I have been thinking about that for a while now and when you think of it, an interrupt controller is not much more than a limited use microcontroller pre-programmed with some kind of interrupt servicing logic.
Thinking along those lines, it should be doable, (Easy? Dunno.), to take one core and program it as a dedicated interrupt controller using locks and a shared memory pool to communicate with other cores that wish to use its services. In fact, with a little more effort, it might be able to program something in assembler that would dedicate a core (say #7), to act as a “programmable” interrupt controller accessible by the other system cores.
With a little bit of handshaking between the devices via shared memory – a particular core could request interrupt services in a particular way, (i.e. interrupt prioritization, passing an interrupt ID, etc.), to make this a general purpose “device” as it were. The only drawback is that any core wanting to use the services of the “interrupt” core would have to poll for a status bit/flag/whatever to see if there is any mail. Which, from a design standpoint, gets under my skin. But that’s me. Maybe when I get the time, (yea, right!), I’ll sit down and write a general purpose interrupt controller program for the Propeller. BTW, if you want to take my analysis and put it somewhere, maybe in a “Why no interrupts?” FAQ, feel free to do so.
If I am understanding you rightly, in a video role, you have multiple cores running the video - one core retrieving the data and streaming it out the video pin whereas another, core(s) act as a pre-processor, assembling the video data, so that the streaming core can send it. And rather than using interrupts, they sync through a shared memory pool. Right?
Thanks again!
Jim (JR)
I have a Propeller "Quick Start" board, (model 40000, rev A). Is this what you mean by the demo board? It sure doesn't look like it, I'd LOVE to find a schematic for the Quick Start board so that I know what to hook where.
Thanks again!
Jim (JR)
Here's the webstore page for the Demo Board. There's a link to the schematic under the RoHS banner.
There's a link to the QuickStart schematic on this webpage.
The Propeller has no way to do this. One cog cannot force another cog to do anything other than stop (be reset) and one cog cannot access the memory of another cog. A cog can wait for an external event, but this is hardware polling, not interrupts.
Since Spin is interpreted (not directly executed by the hardware), it would be possible to make a modified Spin interpreter that uses polling to create an interrupt capability for Spin. The same thing could be done with the LMM and XMM interpreters used for the C implementations on the Propeller, but that's not the same thing as a hardware interrupt facility and it would significantly impact the speed of the interpreter.