Possible Video Separation Ideas

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Post Reply
Sugarplum
Posts: 93
Joined: 30 Sep 2020, 22:19

Possible Video Separation Ideas

Post by Sugarplum »

Many of us have pondered ways to get the video processing out of native code. I've pondered different ideas over the past couple of years. This thread is intended to be a place to have them in a unified place.

Partial Measures
First, we start with partial measures.

For those who don't want to use the Gigatron for gaming, they could modify it to include a monochrome mode. Then they can send 8 pixels at a time, add a shift register, and have 7 free cycles between each pixel group. Thus an entire frame could fit in 2400 bytes and there would be only 20 bytes sent per active row. It is still bit-banged, but there would be far fewer data to bit-bang. This would require a ROM rewrite and compatible software.

The line repeater project makes it possible to have a full screen while only sending 120 rows of data, allowing the Gigatron to send in the fastest mode while still filling the screen. If one wanted to, they could rewrite the native ROM to remove the mode selection to save a few native cycles, or they could somehow code in a speed selection for compatibility since some of the games are more challenging to play in the fastest rendering mode.

Moving from there, you could have an external frame buffer that could include the above idea. Then the Gigatron wouldn't have to work every frame, or necessarily be in sync together. One would likely need to rewrite the ROM so that nothing is sent to the port when vCPU changes nothing in the video. The question then is how the video interface would know when to overwrite the external buffer. However, this would still be inefficient in that changing a single byte could trigger an entire external frame overwrite.


More Comprehensive Changes
Over the past few days, an idea for using an FPGA to make a "passive" video coprocessor/controller/accelerator came to mind. On the native code side, this would require rewriting the ROM to strip out the majority of the video handling. The bit-banging from RAM to the port would be removed. As for syncs, one would want to leave them. Hsync would be needed for sound (unless moved to the coprocessor) and Vsync would be needed for the keyboard/game controller and any software that simulates an RTC. As for installing it into the Gigatron, it could go on a card that replaces the RAM and includes everything included in the I/O controller project. It could include its own DACs and include ribbon cables to replace the resistors or resistor packs on the board.

How the above would work would be to snoop the address and data lines and to shadow the video (or even sound) I/O addresses and use them from the card's own memory. So it is storing what goes into the Gigatron's RAM as it writes and imposes no demands on the Gigatron. So it would have its own frame-buffer and sync circuitry and work completely autonomously from the Gigatron. The line-quadding would be inherent to the design. So the native software does not have to generate the syncs for it (though it may need them for other reasons).

The above is just the start. It can be made to do more than the Gigatron. I've wondered how to include things like display lists, text mode, and more, and it could be simple. One could repurpose the redirection table. I don't know of any reason why the redirection table should be messing with Page 0, so assigning Page 0 could be the "magic number" in the first indirection table entry to let the controller know that something other than the default is happening. Then the offset of the first entry could then be the mode or "opcode." So this could tell the controller to use text-only mode or to use a display list. Or maybe the last entry could be used for this instead to minimize artifacts when switching modes. And some of the modes could be non-immediate so you can keep the last screen displayed up while switching modes.

Plus, the above idea could possibly add non-video features. For instance, the sound could be moved there. If doing that, I'd keep the note table and software wavetables in ROM/RAM. That way, custom sounds can still be added. But the tables could be shadowed by default and be used from the controller.

As for adding I/O features or math coprocessing, that would be more complicated. The above can all be done in a passive read-only fashion and requires no DMA. But if you need DMA writes to handle reads from external devices or to pass back a mathematical result, it would take some interesting ROM changes. Essentially, one way to do this is to have the Gigatron native code in a spinlock, and when the external controller sees this, it could put a fake value on the bus or latch the bus while the Gigatron is reading the bus. Then the controller directly accesses the RAM which is not connected to the Gigatron at this point, and then the controller sends a signal to reconnect the RAM. Then the condition needed to exit the spinlock is met. An example would be math coprocessing. Let's say you have an address to pass the FPU opcode and addresses for the operands and results. So the FPU could change the opcode byte to 0 when it is done. Using the spinlock, the Gigatron is stuck in a loop until the byte is 0. So you could latch the opcode so that is all the Gigatron sees, then disconnect and manipulate the RAM, and switch the RAM back with the opcode byte cleared. This is just a workaround so true DMA or a Halt line would not need to be added.


New Designs

The most drastic would be to create a new Gigatron-like machine that is fully compatible. One could include concurrent DMA. Thus you'd have at least 2 "threads" that run all the time. Most or even all of the previous ideas could be included. Some things could be added to make even bit-banging easier. For instance, if the Gigatron had at least 2 more registers, then bit-banging the current resolution at 12.5 Mhz or faster would be more feasible since vCPU instructions could be interleaved with sending the video data. That would require integrating the rest of the I/O to prevent I/O races. Everything could be done the Gigatron way. However, this method could introduce software races. One way to handle that is to have an I/O controller that will selectively throttle the CPU. So if the video changes get ahead of what the video controller can handle, it could throttle the CPU so the code won't get ahead of the video and sound.
Sugarplum
Posts: 93
Joined: 30 Sep 2020, 22:19

Re: Possible Video Separation Ideas

Post by Sugarplum »

I am curious what others think about the idea of an output-only snooping controller. That seems like a less-intrusive mod and really doesn't require a new board, although it would be a good thing, IMHO, to include on a respin. It could be made onto a board that plugs into the SRAM socket. Purists won't like the idea of an FPGA, but one can think of it like an ASIC, and there were custom video controllers and coprocessors in the '80s.

The other seeming objection to using an FPGA comes from fear about voltages. Since it would be an output-only device, the data, address, and control lines can use resistors or individual resistor packs, and optional Zener diodes past the resistors. Video and optional sound would get new DACs that are calibrated to what the FPGA board puts out. Actual level shifters would not be necessary due to going only from high to low and sending nothing back. If you use a Digilent A7 FPGA board on the daughtercard, the Vcc is 4.5 volts tolerant, and there is voltage regulation on the board for that.

To get the output to the external ports, the resistors and resistor packs could be removed from the motherboard and the outputs past them would connect to ribbon cables. If one is concerned about signal integrity, they could wrap the ribbon cables with foil tape, optionally ground the tape, and then roll it up and use heat shrink tubing (with or without a ferrite bead).

As for the mainboard ROM, it would need to be rewritten. One can remove all the screen output code, but it would be necessary to keep the software syncs for software compatibility and any devices that are not implemented on the controller (such as the keyboard). One might want to either remove the mode selection altogether or change it to a speed selector. If the sound is moved to the controller, you'd still want to keep the sound tables. The controller could use its own for expediency and detect if they are being written to and update what it uses. Plus they would be needed on the Gigatron side in case they are used for math by the software. And character tables would still be needed for existing software compatibility, though the controller could add new modes that rely on its own tables.

The video repeater would not be needed since that would be integral to the design. But an advantage over that is that in default mode, you'd have 19,200 extra cycles in addition to the 57,600 cycles saved by doing HW quadding. And if you do sound on it (or even the lights), you can save a small number of cycles. And this could probably be overclocking-friendly.

Speaking of sound, if that is included on the controller, the sound generation could be removed from the Gigatron side. And really, there are more options for enhancing the sound. For instance, there is nothing that says one can't use a 10-bit adder on the controller and take the upper 8 bits as the output, and without interfering with the Blinkenlights.

As for the internal operation, it would be a matter of snooping the address bus when /WE is active and looking for relevant addresses. Then it can store the relevant data to whichever memory that's desired on the FPGA board and use that as needed. It can use whatever memory mapping it wants as long as it can translate the addresses. For crossing clock boundaries, one would probably want to pipeline things, so if the cycles are off from each other, the data could still be valid between cycles, etc. Plus the board could use the software v-sync to calibrate itself.

The controller could add modes and features for aware software. One way to do that could be to use the first entry or so of the indirection table. One could set the page to 0 since it is assumed that the indirection table would never use that. Then the next byte can be the "mode" or "opcode." At this point, the screen would no longer be updated and would be working entirely out of the controller's frame buffer. To resume the default mode, one could restore everything needed that's corrupt and change the first page entry in the table back to the default value last. And for changing modes without artifacts, there could be store-only modes to send the new data to a different place on the controller before it is needed. Then the mode byte can be changed to the active mode.

Interesting ideas do come to mind. HW sprites could be built into the controller. If one wanted to, they could have a mode where it is stored in a column-major format (a little more complex on the controller end) to where near "endless" side-scrolling could be done. In that case, use the invisible mode to add 120 more pixels and then tell it to move to that. Of course, memory on the Gigatron side could be a constraint, unless mass storage is an option and can work fast enough to load images to the indirection table to use as a window into the controller memory.

A text mode would be nice since one can store ASCII with perhaps attributes to the local frame buffer and the controller could convert them to pixels. That could actually save memory if you want to write games that use the text mode. And extra characters or a completely different character set could be added. Just think of taking the best of the drawing characters and symbols of the Atari computers, the Commodore machines, and even MS-DOS, and using them for games that simulate graphics. Snake could take advantage of that and simulate a higher resolution (like the QuickBasic version that uses text mode and uses the special characters to simulate pixels at "double" the text mode resolution). And things like adventure games, simple things like Minesweeper, etc.

Mixed-resolution modes even come to mind. For instance, why not a sprite, texture, and character library on the card that is made for 320x240 or 640x480. But that would require some clock magic. The pixel clock could be 12.5 or 25 (or 25.1 if you want to be accurate) and stuff coming from the Gigatron gets doubled or quadded across while the library items could be displayed as-is.

Mixed-data modes could be done too. So one could emulate Atari 800 behavior and have split-purpose screens, with a box on the top or bottom for text information and the main box for graphics.

And if one wants to add other things, they could use multiple DACs and have more colors, or alternatively, hardware dithering, and/or add automatic banding reduction. For dithering, if you use a higher pixel clock, it can alternate pixels to produce in-between colors. And not sure if this would be a good idea, one could reverse the order of the dithering with each frame, but that should be optional and not enabled by default since I don't know how that could affect migraine sufferers and epileptics. It might not be bad if the colors and intensities are close, but if you stray too far when changing dithering with each frame, that could be undesirable. We wouldn't want folks messing up in games if they were to avoid looking at critical parts of the screen (and it may be worse in the peripheral vision, so that could cause object fixation instead).
Sugarplum
Posts: 93
Joined: 30 Sep 2020, 22:19

Re: Possible Video Separation Ideas

Post by Sugarplum »

With the video coprocessor idea, I worked out some other questions. If one wants to dedicate an FPGA board, one would probably want to add as many features as possible. I mentioned using it for higher math functions too. That raises the question of where to put the FPU "register" area. After all, every byte of the Gigatron is spoken for. Then it dawned on me. Since the controller would have multiple modes, this shouldn't be an issue.

Since the controller board would shadow the RAM as it is being written (which is not the best solution since the Gigatron's RAM would still be written to), then the controller could have a mode to "blind" it to changes in the I/O areas. So when in those types of modes, the RAM could be repurposed. The controller would use its own RAM for video, sound, etc. And when switching the mode back to default, that shouldn't be a problem, since the repurposed RAM locations would be safe until the software overwrites them. So partial updates to everywhere else but the FPU message area would leave the FPU message area untouched. By the time you'd want to change the video RAM in that area, you'd have likely read and used that RAM, making it fair game for the controller to use for the original purpose again. So at least 18.75K of RAM could be used for math, audio samples, sprites, file I/O, or whatever, without interfering with its use as a frame buffer and so on.

And TBH, for a new build, one could give the coprocessor/controller its own 64K area and have new native instructions to use it. Then the software would have much more RAM available. But for an existing Gigatron, this strategy of using the RAM for different purposes would work well enough. It is good to avoid multiplexing in many cases for performance, but this would be a good case for using it. But to keep compatibility, the "blinding" mode and using the controller for other things would work fine, even though really if you have RAM elsewhere, you shouldn't have to use the main RAM. This controller is there to intercept the signals and doesn't care what actually ends up in RAM. But a default Gigatron needs it in its RAM to work.
Post Reply