[FYI] VGA, 40x15, single cog, per cell colour/palette, ROM font
kuroneko
Posts: 3,623
Based on [post=1210076]Jim's wishlist[/post]:
- uses only 1 cog
- provides 640x480 VGA with 40 columns x 15 rows
- consumes little memory (1-2 words/char)
- provides multiple colors (at least 4 colors/screen and at least 2 or 3 colors/line, not just 2 over the entire screen)
- displays characters using the full 16x32 built-in ROM font.
'' mailbox layout - full colour driver '' '' long[par][0]: screen: [!Z]:addr = 16:16 -> zero (accepted), 2n '' long[par][2]: colour: [!Z]:addr = 16:16 -> zero (accepted), 4n '' long[par][3]: frame indicator
'' mailbox layout - paletted driver, 4/4 split '' '' long[par][0]: screen: [!Z]:addr = 16:16 -> zero (accepted), 2n '' long[par][1]: pal/user: u:[!Z]:addr = 1:15:16 -> zero (accepted), 2n/4n '' long[par][2]: colour: [!Z]:addr = 16:16 -> zero (accepted), 2n '' long[par][3]: frame indicator, [COLOR="#FF0000"]vcfg on startup (14:9:9)[/COLOR] '' '' The pal/user parameter is encoded as follows: '' %0--//--- palette address if not zero '' %1--//--- custom character base address
Comments
That "Santa" is Kuroneko, of course, and that "great big package" is a versatile new 40x15 VGA text driver (eh, I'm not sure what the "snow" is in this analogy).
Yes, it appears that you hit all of my wish list and then some! That's just fantastic! Cool beans!
So far, I've only had a cursory look at the code as I was enjoying playing with the driver to put text on the screen.
But from that quick inspection, it looks like your main buffers in the "waitvid.40x15.ui" object consume only 600 bytes for the scrn[] buffer for the text and 1,200 bytes for the plte[] buffer for the colors (do correct me if I'm wrong). So, you've implemented this using the Propeller's full 64 VGA colors (2^2 * 2^2 * 2^2). So, we can have any combination of foreground and background colors that we desire.
That's why I say it goes beyond what I wished for, as I would have been pretty happy with just 4 or 8 total colors. But I'll take it!!! Well, it does come at a price of an extra 600 bytes, but it should generally be worth it, assuming one has memory for it.
But that does make me wonder if it would be (theoretically) possible to create a version that used a single byte for the colors similar to Chip's 32x15 VGA text driver, the one with the eight combinations of foreground and background colors. Maybe there's something about how the driver itself handles things that would make that difficult, don't know.
By the way, I was curious about why the user needs to specify 4 octal digits for each of the foreground and background colors instead of three. The last (least significant) digit will always be "3" won't it (or maybe it's a "don't-care")? Maybe those bits relate to the HV bits somehow, but, offhand, I'd guess they'd get masked off. Anyway, does the user specifying 4 digits instead of 3 at the top level speed up fills or something in the .ui object or something similar? Or was that just a convenient way to code it? Whatever the reason, we can surely type another "3" here and there.
Anyway, my memory target was 1 to 2 words per character, and you're right in the middle of that at 1.5 words/char.
By the way, I was curious about the rationale behind that mailbox object. Guess I should look at that again. Also, it seems like you name your objects in the style of Java or something, almost like we had name spaces. You seem super organized. I guess you have to be organized (among other things) to be able to crank out a driver as fast as you did this one.
Okay, I want to get back to "playing" with this new driver. Thanks so much for pushing the envelope on this one!!!
If the colour components are part of a string you can't have 0 bytes in the middle of it. So the sync locations are a convenient place to avoid that (the driver ignores sync in colour anyway). Regardless, even leaving them 0 would force you to specify 4 octals because sync is in the least significant digit (%%rgbs). For the two out calls in the random section they are redundant (force of habit I guess).
You can obviously change the UI to accept %%rgb and adjust for the internal format (unnecessary overhead) but if you write to the palette buffer directly then %%rgb? is required.
Can you elaborate? Mailboxes are usually used to communicate with the driver, in this case only the frame sync is delivered but the UI ignores it. Other driver models allow for dynamic relocation of screen/colour/font buffers so they need some space to communicate.
The important thing is just the driver. UI and demo are just for showing something, feel free to put you own creation(s) on top of it.
So, do the "6/2" and "4/4" splits for the fg/bg colors refer to a total of 8 bits (1 byte)? That is, there could be either 4 or 6 bits for an index for the foreground color, with the remaining bits as an index for the background. I mean, would a palette selection byte for each character exist and be split up into two index parts, either 6 bits and 2 bits or 4 bits and 4 bits?
If so, I believe that, for each character, the former would provide for any one of the 64 possible colors as a foreground color on any one of 4 background colors (selected from the 64 possible). And the latter would give any one of 16 possible colors (selected from the 64 possible) as a foreground color on any one of 16 colors (selected from the 64 possible) as a background color, again for each character. That's assuming that you don't need to reserve the last 2 bits for H&V, as I suppose the driver would look up the actual color values from the table and shift things to make room for H&V. Anyway, the bit patterns (of the split) would be indexes into a color table, not the actual colors themselves (which is why I guess you said palette). Have I got that right?
Offhand, I think I'd prefer an even split, as I'd like to be able to do reverse video colors for several combinations of fg/bg on the screen. For example, I might want a red bar (made from spaces) across the top of the screen, a blue center text area, a white bar across the bottom and maybe a text field in the blue area somewhere. If so, I've already used up my 4 possible background colors. And I still might want to do some other text on a different background as a special effect.
As a side note, I might want to wire up only 3 pins for for VGA (one pin for each color), as opposed to the full 6, not including HV. In that case, 3 pins only allows for 8 colors (2^1 * 2^1 * 2^1). However, offhand, I think the same analysis applies about wanting more background color possibilites to choose from than just 4.
Anyway, 16 possible foreground colors (on 16 backgrounds, even if they used the same color set as the foreground) is a lot of possible colors on the screen at one time. And I think the user would be hard pressed to tell that we didn't have the full 64 available (for the foreground, anyway) on screen at one time.
By the way, would we be able to change the palette colors at will (in the table), such as to change colors sets between pages or to maybe do blinking characters without rewriting the text, just by changing the colors in the palette table corresponding to the fg/bg byte(s) of the characters that we wanted to blink/change? That might be nice.
Anyway, I realize you've got your hands full at the present time, so don't feel compelled to think about this, if ever, of course. But I noticed that I hadn't responded to your question above and I wanted to address it (it turned out to be more complex than I realized). Also, I'm partly just trying to confirm my understanding of what you were asking. I'm afraid I've overlooked something, and you might not be able to access the font data and apply the colors fast enough (though the current driver is working).
Also, if using indices, as a somewhat special case, one could have two different indices that resolved to the same color from the color table (two entries in the table with the same value). For example, all the blue text on screen of exactly the same shade might be linked to the color table by two (or more) indices. Thus, when one of the color entries in the color table was changed (for one of the blues), only the blue text that corresponded to that table entry would change color, not the other blue text. But using that to change text color probably isn't so common, other than for blinking/flashing text, which can also be done pretty effectively for a limited amount of text by simply drawing over it, so no big loss if it isn't there.
As an aside, where such instant color changing capability would come in handy is with complex graphics shapes (which we don't have in a text driver, of course), where the entire shape, even discontinuous, could have its color changed instantly by changing the corresponding entry in the color table (that's one reason I like the color table of the P2). For example, say one had an app with country flags which needed to be colored appropriately by cycling through various colors by clicking. With a color table, the color could be changed without having to redraw any potentially weird/complex shapes. Such would be good for highlighting button presses, too (though I'll admit that video graphics these days are powerful enough to redraw everything without using such a table trick and basically need to anyway to do animation).
But, again, for text, there's not much of a use case for instantaneous changes to text color (although one could fake clearing a portion of text that way by setting it to the background color). So, actual colors in the 6-bit portion of the color byte seems the way to go and saves the memory that would be needed for a foreground color table.
But as far as what's the best spit, 6/2 or 4/4, though I said what I said above about being worried about not having enough background colors on screen at one time, I guess 4 is pretty good for most cases (but I definitely wouldn't want less). So, don't let that cloud your decision if you decide to attempt a new driver, i.e., code it as you see fit (we will gladly use it either way).
And if using a 4/4 split, I'm guessing just one table is enough: [1] for text, I think 16 colors is more than enough, as that's a slew of color combinations, and, [2] one table, as opposed to two, would save memory, maybe only 16 bytes for the table plus space for the code loaded via eeprom, but every byte counts on the Prop and I'm not sure there's much advantage to having a separate set for the background colors. Actually, I didn't try to come up with a use. I guess if people are picky about the available color combinations, there might be something to having two tables. It is actually a bit tricky to choose fg/bg combinations that work well, though high contrast usually works best.
Anyway, 6/2 or 4/4 (the latter with 1 or 2 tables): we'll be thrilled whatever way you go, if you do take a stab at it (and from what I've seen of you recently, you're probably just putting the finishing touches on the code now).
Small is very important, and it looks like this is going the right direction.
The number of rows is a bit limiting though. Is there no way to get 40x30 out of this driver?
The standard VgaText.spin driver will do 32x30 just by redefining cols and rows. That is very useful for program text editing.
Regardless of my own requirements, it looks like I'll have no trouble making simple libraries with this 40x15 code or variations of it.
Thanks Marko.
--Steve
Palette support is on the way (seems there is enough demand now). As for cursor positioning, what's wrong with the ESC sequence? But yes, a method (e.g. gotoXY) is easy enough to implement. Note that the UI object I use is just part of the driver demo. Feel free to wrap anything else around the low level driver depending on what you are used to or what you need.
You're right. My parameters are a bit different (and in C).
Can you try the attached binary?
Thanks.
Thanks Marko.
This is a good data point. My monitor must be very forgiving.
Thanks for doing this, Marko. This new version together with the original version are bound to be quite useful to many folks.
So far, I've only put a few letters on the screen, but it seems to work as advertised. For now, the user interface to the driver has been "left as an exercise to the reader," as they say, but that's totally understandable, as people can program it the way they want (and also this is early version of the driver, not necessarily the final one).
Regarding going for the 4/4 split, I think that was a good choice (such that the BG colors aren't limited to 4 simultaneous ones). And as far as using 2 tables for the FG and BG colors, that was a good judgement call on your part (I was being too greedy to care about saving a few bytes there); it's more flexible at little cost.
Again, to anyone reading, I think this looks great on the common/smallish 800x480 screens, stretched from 640. And getting an extra 8 columns helps a lot and makes for more normal-looking characters (as I feel that 32 columns gets stretched a bit much on a WVGA screen).
Also, the Parallax font, which consistently has font strokes that are three pixels wide, is a beautiful font and looks really good displayed full-form at 16x32 (which is not to say that it wouldn't also look good displayed with half-height characters for 30 rows, particularly on larger screens).
Thanks again, Marko, for putting this together and figuring it out. Bruce, in "Bruce Almighty" was "Mr. Exclusive"; you're Mr. (Mission) Impossible.
Red Alert: 1200 bytes, people! 600 for characters, 600 for the fg/bg color pairs, one pair per character. What more could you ask for!
In the UI object, the init method issues an out(FF{== 12}) (clear screen) which doesn't work anymore with your changes (you should use $01 now). Also note, FF is not $FF.
Clean, great color, fast and easy to use.
It amazes me how freely some of the best I've ever come across offer their talents to us plebes... thanks Kuroneko.
This video driver will find it's way to all of my vga applications.
Regards,
sm
Note that you don't necessarily need to define(/reserve space for) the whole array if you use less characters.