VGA text driver questions/concepts - Q's probably for Chip - vga streamer interrupts wkg
I have the VGA demos that Chip released eg VGA_1280x1024
I will be attempting to put pasm text screen handling into this object but I am not sure how to insert it between the streamers operation of painting the VGA screen (within the same cog).
How do I ensure that I don't let the streamer under-run while maintaining the screen buffer ie writing characters to the screen, handling control codes, and clearing and scrolling?
I presume I am going to need to perform some timer style interrupts so I can keep the streamer fed. While not feeding the streamer I will then be able to perform the other screen functions? But I am unsure how to go about this. Any guidance would be appreciated.
Guess I should also ask, has anyone done this already?
@rogloh Is your driver capable of this (without external hyperram)?
Comments
As background info, here is the field display loop
You need to get the video running on a streamer-empty interrupt (XMT event).
Here is a program that generates NTSC on interrupts, along with one that does it in the main code. To make this work for VGA, you'll need to break the VGA program into pieces that can run on interrupts, instead. Looking at these two programs will show you what the difference is.
To get that Space Invaders emulator running all in one cog, we did the video on interrupts, so that the 8080 emulator could take most of the time.
Cluso my video driver COG in text mode is screen buffer based and requires the client to put character data into the screen buffer, so it isn't a terminal as such. I have included other SPIN2 APIs to select the active region, and FG+BG colours and basic tx(), out() APIs etc for printing which can conveniently be mapped to SEND from SPIN2 clients. Actually I will be releasing its update very soon with the external memory support, I have finally got it working again with PNut and PropTool a day or two ago instead of just in flexspin as the first release used to be. Just wondering if I'll release it before more demos and doc updates are in place...
@"Ken Gracey" , if you need to use my VGA driver soon in Proptool let me know I can shoot you an updated build that works.
Here's Chip's code again but without the ASMCLK macro.
Ray, I also created a VGA text driver that supports ANSI escape codes and up to 1280x960 resolution (that one requires a 16 pixel wide font, with 8 pixel wide fonts it only goes up to 1024x768). Actually looking at the timings it should be able to do 1920 wide, I just haven't tried that. It's text only, but of course the font can contain graphics characters so you can do some old-style graphics that way.
For my object I feed the streamer one character line (8 or 16 pixels) at a time. Timing can get tight at higher resolutions, but using wider characters (like the P1 ROM font at 16x32) really helps. The pixel depth also complicates things. Monochrome is the most efficient, but oddly enough using true color (24 bit color) is the second most efficient, since in that case we can just feed the raw color values to the streamer. The character data is slurped out of HUB ram during the horizontal blanking and then fed to the streamer from COG ram durinig the active video. No interrupts required.
I have used ER Smith's ANSI - VGA driver with great success. It is very solid and easily modifiable for your specific use.
The screen sizes are especially useful for both low & high resolution. I use the original P1 font for all of my work.
One thing I would like to add are either double height characters - And/OR - Custom designed bit-mapped characters using the P1 font 16x32 format
I’m another fan of ERSmith’s VGA driver. Its been bulletproof for me and it is really simple to hook up to FlexBASIC’s PRINT #n command. Once you initialize it, printing to the VGA becomes as simple as:
print #3 “Hello world”
Thanks Roger. Seems it's not what I'm after as I just want basic VGA that I can add the text code into.
Looks like I have a selection of text code to choose from too
Chip & Evan,
Thanks. I'll take a good look.
I think for what I'm doing, it will be a combo of this.
Eric, PropGuy2 & JRoak,
Thanks, and for the vote of confidence too.
I'll take a look as this sounds very useful. Perhaps a combo of this with Chip's interrupt streamer will work nicely. I can always add in extra things if it's not there. I needed to do some basic pasm code for driving my LCD including scrolling in sw (even tho I removed it) so I have some of that to choose from too.
While I never cared for ANSI codes way back, it is quite common and possibly makes more sense than VT52/100 ???
Evan,
Perhaps you might like to add the asmclk code to the P2 Tricks and Traps Reference thread?
https://forums.parallax.com/discussion/169069/p2-tricks-traps-amp-differences-between-p1-reference-material-only/p1
Ah, what I did was hand crafted the clock mode constants. It's not as simple as generic code replacement.
Thanks Evan
I didn't look close enough to realise it was tailored to the requirements.
So I've looked at the various pieces of code. Thanks guys
I am trying to write a VGA Device Driver that will fit into my stable of code that uses my same format object (the one based on jonnymacs fullduplexserial) so that code can be independent of the attached devices.
I know this will never be perfect. For instance, VGA might support ANSI sequences, but what about serial? This depends on what is on the other end of the serial.
For instance, my LCD driver cannot do scrolling properly, so the cursor just flows from the bottom to the top and each time the cursor moves down a line, that line and the one following are cleared. Not ideal, and not ultra-fast either. But it serves the purpose.
Now for Text VGA, I only want to allocate 1 cog do do this. So within the cog I need to...
Most of the code posted above is unfortunately in spin and of course this needs to be in pasm. However, I've done all but ANSI already in pasm (I have a cursor in P1 1-pin TV code) but not in LCD yet.
@Cluso99: Why require that the ANSI processing happen in the VGA cog? If it happens in the original COG everything is much simpler -- the VGA cog can then stick to the one job it really needs to do (output the video) and the other COGs can handle any time consuming processing.
Cluso, so your intent is to have a COG that just takes an input stream of characters and puts them onto the screen without any API to call as such?
If the client that wants to print text still runs SPIN2 it could call my video driver API to do exactly what you need for these things (apart from interpreting ANSI at this stage) and can be conveniently be hooked into printing text via SEND redirection. I'll send it out soon.
Eric,
Because the user code is totally decoupled. The user doesn’t know what is connected. Ansi could be sent within the user section.
However, I don’t want to burden the formatting object. I may execute ansi sequences in the vga pasm cog as its not difficult to implement a subset.
Roger,
I’m using a decoupled hub buffer(s) to communicate with device drivers. I can substitute the device drivers on the fly too with existing compiled code. So the driver must pick its characters from a hub buffer. I'm sure that could be done with your driver but then there wouldn’t be soace to implement the screen handling code.
SEND doesn’t work in this regime.
@Cluso99: User code can be decoupled without having to force things into a cog. I think this is revealing a flaw in your framework: does every driver need to use a whole cog for its output routine? What if it's some kind of trivial thing that can easily be run with just a smartpin?
Maybe it would be better to provide a jump table for the I/O routines, instead of a buffer. Then the driver would still be de-coupled, but the code could run in the same COG if it wants to.
Okay, sounds like you have a different display model where things are being done more automatically, under the hood. I can see some usefulness in some cases, like if you wanted to print from PASM cogs etc, but at least personally I'd still like to have control from SPIN2 to display whatever I want and get to use some richer APIs for various things. This SEND redirection is useful enough for me at the moment.
Yes, it’s a different model, on the way to a P2 OS where different device drivers can be loaded and/or reloaded at run time.
I’m really liking the simplicity of using interrupts to do the actual vga display. I think i can make the text font generation under interrupts optional which would permit graphics too, perhaps for part of the screen too.
Chip,
I’m not quite understanding the streamer / rdfast/ setq interaction.
So presume I have the streamer running under interrupts. I’m using text only, so a font and a color lookup. I also want to do text screen processing, which is why I need the streamer under interrupts.
Currently every character line generates (for an 8x8 font) 8 pixel lines. If we except that one line (usually the bottom line) is blank, then it’s a wasted line that just outputs blanks.
So here’s the idea. The first line of pixels we make blank - this allows us to fetch the line of characters into the cog/LUT, and then on each of the next 7 pixel lines we process those characters into a line of pixels.
Can we use SETQ/SETQ2 RDLONG pair to fetch the line of characters while we output a streamer pixel line of background color?
For each of the 7 pixel font lines, we process (lookup) the pixel line within the cog/LUT and use SETQ/SETQ2 WRLONG pair to write back the pixel line to hub ready for output by the streamer on the next pixel line. (We will need a two pixel line in hub to ping/pong).
Would this work? And do you think I might gain some additional time for the screen processing? Or can you think of a better way?
It seems the cog can process text mode in the real time without any tricks with blank lines.
This thing while not optimized, displays one line of 4 characters : about 60 cycles of 320 available between xconts used here. I am now trying to use 2 sets of LUT registers to change colors every 4 chars=one xcont so every 16 lines I read 50 longs to the cog using rdfast while displaying a border - HBlank period may be also used.
Because the streamer has immediate->LUT->pins modes, you could do such video on interrupts using SETQ+RDLONG with subsequent XCONTs, without even interrupting RDFAST/FIFO being used by XBYTE.
I am going to move 16 longs of the Spin2 interpreter from LUT to register space, so that we'll have 16 longs free, usable as 1/2/4-bit LUT colors for streamer use on interrupts.
Thanks Chip.
Sounds great. This cog is all pasm so no need for spin in this cog.
I can read a line of characters into cog/lut with SETQ RDLONG and then convert each line to pixel data per line displayed.
Scrolling is best done by shifting from hub via cog/lut and back to hub using setq as it would be fastest.
BTW I have already done the pasm code for screen handling (some control characters and scrolling) in my LCD driver in a previous (not released) version before I ditched the screen buffer altogether and just used the LCD's RAM. So in reality, I've just to combine a few pieces of code with the interrupt VGA code.
Being able to use the streamer from LUT concurrently with SETQ/SETQ2 is a real bonus! Forgot that's what the second LUT memory port was for.
These P2 bonuses just keep popping up
On the P1 and monochrome (ie one forecolor and one backcolor) and 80x25 I've done the whole job in a single cog. IIRC scrolling was included but it was shared over multiple scan lines. Of course color adds a lot to the mix!!!
I did a color one on P1 Only 40x25, but I think I made the terminal code really efficient and it supports all the PST commands. It even has a "bell" (basically adding some constant to the DAC on every line until a timer runs out -> slightly distorred sawtooth wave. Just takes a few instructions.)
Chip didn't really answer your original question of can the SETQ+RDLONG be used while the streamer is also using the FIFO to read hubRAM. The answer is yes, SETQ+RDLONG doesn't use the FIFO at all. And I think you'll be needing this mode.
Yes that the key to making things run smoothly while doing video with the P2. I've exploited that capability significantly myself and is one of the more powerful capabilities of the P2 to allow multiple things to happen at once in a COG.
Evan,
Hub is only single port, so streamer and setq couldn’t both have access on the same clock from what I understand the circuit to be - there’s only one 32 bit buss going to the cog/LUT gated to one of 8 x 16KBx32 hub blocks. Guess I didn’t think that part thru.
But the streamer does have concurrent access to the LUT as its dual port and the cog accesses it from the other port. IIRC this is why there’s a 3 clock rdlut and not a 2 clock rdlut. I’d forgotten all this.
I can see some testing on the horizon
That's the neat part about the FIFO. It bursts for the streamer, so the streamer can pace itself without worrying about hub access timings. There is plenty of time for the SETQ+RDLONG to also burst between the FIFO bursts.
VGA using Interrupts
Attached is VGA_640x480_text_80x40_interrupt which runs the streamer under interrupts
I found a couple of traps
' setint1 #INT_XMT
The INT_xxx definitions (as defined in the spin document 34r/s) appear not to work