BMOW title
Floppy Emu banner

Archive for 2008

Boot Loader

Following my experience with the video system, I decided to create a boot loader. It’s a little surprising that I never did this before, actually. While working on the video, after every tiny change to the video software, I had to reprogram the BMOW main ROM and stick it back on the board. I must have done it 100 times, and each time took a couple of minutes of fiddling with the chips, EPROM programmer, and software. What a pain.

Fortunately BMOW already had all the ingredients needed for a better solution, including a USB connection for communicating with a PC. I wrote a fairly simple boot loader program, which I programmed into the main ROM– hopefully my last ROM program for a while. At power-up, the boot loader listens for data from the PC on the USB port. It expects an initial signature, followed by two bytes to determine the download size, then the download data itself, and finally a checksum. The downloaded data is copied byte-for-byte to a fixed address in RAM. Once the download completes, if the checksum matches, the boot loader transfers control to the downloaded program and it’s off to the races.

Using the boot loader allows me to experiment with software changes far faster than before. I can change a couple of lines of code, assemble it, hit BMOW’s reset button, and download the new program using the boot loader. The whole process only takes a few seconds, compared with a few minutes for my old method of burning a new ROM each time.

Read 5 comments and join the conversation 

Mixed Mode Video

Here’s the promised better example of BMOW’s video capabilities. It demonstrates text with different foreground and background colors, and the use of text and graphics on the same screen.

By using two bytes per line to control the video mode instead of to encode pixel data, the video display becomes much more flexible at the loss of a few pixels. Although there’s only a single 256 color palette, it’s possible to switch between different 4 or 16 color sub-palettes on a line-by-line basis for 2-bit and 4-bit lines. You can also select a different foreground and background color for monochrome lines, or switch between character mapped and direct bitmapped video. All this flexibility made the system twice as hard to design, and may not be especially useful in practice. I probably would have been better off without it, but it makes for a good demo.

I had intended to have all sorts of dynamically-generated lines, circles, triangles, and other shapes to show, but that proved to be a much bigger task than I’d expected. It took me a couple of hours just to debug the subroutine that renders the two zig-zag lines you see here! Apparently I’m not the world’s best assembly programmer… I added the 16 color image of leaves at the bottom to substitute for my missing shape parade.

It’s hard to appreciate the quality of the video from this photograph, but it really looks very nice. Pixels look sharp and solid, and colors are uniform. Some of the text looks a bit washed-out and fuzzy in the photo, but in person it’s quite crisp. I’m definitely happy with how it turned out.

I’m not sure where to go next with the video system or BMOW in general. Maybe a better font? Get the system monitor program running on the video display instead of the LCD? Truth be told, I’m getting kind of tired of this project, so I may move on to something else.

Read 5 comments and join the conversation 

25.175 MHz

Some good news on the video front: by modifying the pixel clock and playing with my LCD monitor calibration, video quality is dramatically improved. The pixel stretching stemming from my non-standard 512 pixel horizontal resolution is gone, and even the light/dark vertical noise bands are almost completely gone. Interestingly, it seems they both were manifestations of the same basic problem.

A standard VGA signal at 640×480 resolution has 640 pixels visible horizontally, but there are also an extra 160 “phantom pixels” not drawn on each line, which constitute the horizontal blanking interval. The duration of each line is therefore divided into 800 (640 + 160) equal time intervals of just under 40 ns each, and the continuously varying VGA voltage is sampled once during each of the first 640 intervals to determine the pixel color. In fact, the exact interval duration is 1 / 25.175MHz which is about 39.72 ns.

My problem was that I tried to generate a 512×480 resolution image (using a 20MHz pixel clock), which isn’t a standard VGA resolution. On a CRT monitor I think this would have worked fine: each line would be a continuously varying analog voltage, without any specific number of pixels horizontally. On an LCD monitor it mostly works too, as long as you’re not too picky about image quality, but I’m picky. The LCD monitor was sampling the VGA voltage every 39.62 ns, but I was changing that voltage every 50 ns (1 / 20MHz). So every few pixels, an output pixel’s VGA voltage would get sampled twice, and appear as two pixels on the LCD, creating this chunky stretching effect. And because the voltage sampling was out of sync with the voltage changes, I think the LCD monitor often “saw” voltage changes causes by transient switching noise, leading to the light/dark vertical bands.

I swapped my 20MHz pixel clock for a 25.175MHz one, reprogrammed the GAL that calculates the horizontal sync timing, and bingo! Text became nice and crisp, and the light/dark bands were much less noticeable. With a few minutes of fine-tuning the monitor calibration, I was able to nearly eliminate the bands entirely. So now the video was almost perfect.

I say almost perfect, because I’m still only generating 512 pixels, but now I’m using a 640 pixel clock. I fill up the other 128 pixels with black.  In the first attempt, this meant that the left 80% of the screen was filled with my image, and the right 20% was empty. It looked pretty dumb. My solution was to simply center the image, so now there’s a black column down the left and right 10% of the screen, with the image occupying the center 80%. It still looks a bit odd, but it’s not too bad. The improvement in overall image quality is definitely worth it.

One bonus side-effect of switching to a 640 pixel clock is that I now have square pixels. 640/480 = 4:3 which is the standard aspect ratio for regular (non-widescreen) monitors, so it works out that each pixel is perfectly square. That may not seem to matter much, but non-square pixels are a pain to work with. They make images look distorted, or geometric shapes like circles appear like ovals instead. With square pixels now possible, the main rationale for the 512×400 and 512×200 video modes was eliminated. (I originally included it because it was closer to 4:3 than 512×480 was.)  Those modes never worked quite right anyway– the monitor detected them as 720×400, leading to even more severe examples of the out-of-sync sampling problem I had earlier, with no solution other than to use a 720 pixel clock. I just eliminated those modes completely, and turned them into configuration options of the base 640×480 mode instead.

At the end of this all, I’m now generating a standard 640×480 VGA image, but only the center 512×480 is filled. The image can be configured one of four ways:

  1. 512×480, with one common color depth / text setting
  2. 508×480, with a separate color depth / text setting for every line
  3. 512×240, same as #1, but every odd line is a copy of the previous line, and greater color depths are possible
  4. 508×240, same as #2, but every odd line is a copy of the previous line, and greater color depths are possible

As soon as I can figure out what’s causing BMOW to sporadically freeze-up, I’ll put together some more interesting examples of mixed text and graphics, and post the screenshots up here.

Be the first to comment! 

Text Generation

BMOW is now text-enabled! I stole an 8×16 bitmapped font from the X11 font set, programmed it into my character ROM, and now I can do this:

OK, it would be a more impressive demo if I actually wrote some specific text to the screen, instead of displaying garbage memory as text, but you get the idea.

There are 64 columns x 30 lines shown here. Each character is an 8×16, 1 bit-per-pixel bitmap stored in the character ROM. During normal video operation, bytes from video RAM are passed directly to the palette chip to be converted into colors. During text mode, however, the bytes from video memory are instead used to create an address for the character ROM, along with the least-significant 4 bits of the screen row counter. The correct character byte for the desired character and row is then retrieved and passed to the palette chip. There are 128 (7 bits) different characters possible. The 8th bit is used to invert the character, making it appear as dark on a light background. This can be used to implement a cursor, or create a highlight effect for text.

In this example, the whole screen is filled with black and white text. I’ll try some more complicated examples next. It’s possible to select different foreground and background colors for each line of text, as well as to mix some lines of text with some lines of graphics on the same screen.

Unfortunately a side-effect of my most recent text-related changes seems to be making BMOW extremely crash-prone. It frequently freezes up within a few seconds of power-on. If I remove the text-related subroutines from my boot ROM, the problem vanishes. Oddly, the problem happens if the text routines are in the boot ROM, even if I never call them. I think they’re pushing the system monitor program subroutines into a different address range in the ROM, which must be causing problems somehow.

A second problem is that my horizontal resolution of 512 pixels doesn’t scale well on my LCD monitor. The monitor thinks it’s a 640 pixel wide image, and does some kind of sampling and scaling accordingly, with the result that the text looks distorted. If you look carefully at the full-size version of the photo, and look for instances of the forward slash “/”, you’ll see that instead of looking like a smooth diagonal line, they look chunky, like an extra pixel were in the line. This is not an error in the font, and if you look at other examples of the forward slash, you’ll see that the extra pixels are in different places, or in some cases not present at all.

Maybe I just need to live with this. The only realistic solution I can imagine is to replace the video clock to generate a 512 pixel wide image with 640 pixel timing, with a 128 pixel black border at the sides. Updating the video system to generate true 640 pixel wide video would be too large of a change to attempt at this point.

Read 3 comments and join the conversation 

Video Demo

Yarrgh, thar be pixels!

BMOW’s video system still has many minor issues to resolve, but the critical pieces are all working now. I can set up a video mode, poke bytes into video memory, and see pixels on the screen. I can even display digital photos. It’s almost like a real computer!

In a previous entry, I mentioned that I was having a problem losing VSYNC synchronization when reading or writing large amounts of data to video memory. I never did really find an explanation for that, but I did manage to stop it from happening. I think the problem was related to the mix of logic families among the parts in BMOW’s CPU. Most of the video system uses 74HCT series logic, because I had some idea it would be faster and use less power than the 74LS series parts used everywhere else. With the oscilloscope, I observed some crazy ringing that occurred when the 74HCT244 bus drivers turned on to drive the CPU address bus onto the VRAM address lines. I tried replacing the bus drivers with 74LS244s, and the VSYNC problem vanished. Strange, but I was happy to have a solution after having spent too many hours over several days on other failed attempts to solve the problem.

I then turned my attention to actually using the video system. Little by little, I puzzled together what bits I needed to stuff where in order to make something interesting happen. At first it took some time just to find a reliable way to set the video resolution and clear the screen. Did I mention that my design is way too complicated? Eventually I reached the point where I could set pixels at will, and then nothing could stop me. Here’s one of the early pixel tests, which I think is at 128×240 resolution @ 256 colors, showing the eight basic colors of black, red, green, blue, yellow, cyan, magenta, and white. This also demonstrated I could control the palette correctly.

(Click on the images below to see larger versions.)

Here’s a color test, similar to the simulated color swatches I showed a few months ago, but this time running on the real hardware.

This random pattern at 256×480 @ 4 colors gives you a feel for the resolution possible at that color depth.

Here’s a similar random pattern in black-and-white at 512×480. It actually feels quite high-resolution, and should make it possible to create some very detailed (if colorless) images.

Random noise at 128×100 @ 256 colors, one of the comparatively few combinations of video settings that allow for nearly-square pixels.

This was my first test of importing a digitized image, in this case a photo of my daughter smeared with yogurt. The resolution of this image is actually limited by the size of my boot ROM, and not the video system. I only had 8K free in the ROM to store an image, which limited me to an image at 64×100 @ 256 colors. The video system supports up to 128×200 @ 256 colors, I just need to find a way to get the image data in there.

Eventually I went so far as to create a BMOW screensaver, with the 64×100 image of Becky bouncing around the 128×200 screen.

It looks decent, but it’s S-L-O-W. There are a couple of reasons for the slowness. The memcopy code I wrote to blit the image into video memory is pretty inefficient. With some care, and perhaps with some new instructions added to BMOW’s instruction set to help optimize memory copies, I think I could speed this up at least 2x, possibly as much as 10x.

The second reason for the slowness is more interesting. The screen saver waits for the vertical blank period at the end of each video frame before the CPU tries to alter video memory. So most of the time when the video subsystem is scanning memory and spitting out the image to the monitor, the CPU is idle, waiting. During the brief VBLANK period, if updates a few pixels, and then goes back to waiting when the next frame begins. This effectively cuts the video memory bandwidth to about 10% of what it would be otherwise, but it avoids contention from video memory between the CPU and video subsystem.

Here’s what the same screensaver looks like with VBLANK synchronization disabled. You can see that it animates much faster when the CPU isn’t waiting all the time, but it generates noise in the video image whenever the CPU makes a video memory access. The result looks pretty terrible.

I posted my “hello world” video test entry on June 24. That was a stand-alone test circuit using just five chips to create a low-resolution, fixed image. I honestly didn’t think it would take anywhere near this long to deliver on that proof of concept and get BMOW video working, but in retrospect there were quite a few challenges beyond simply getting something to appear on the monitor. The finished system interfaces with the BMOW CPU so the image can be updated on the fly, supports palletized color and dozens of different video resolutions/depths, and also boasts a character generator mode (not quite finished). I’m pretty happy with that set of features.

Read 11 comments and join the conversation 

Video Bringup: Part 2

Video works! Er, sort of. After fixing the HYSNC problem, I experimented with the palette chip, just to prove it was working. With a few bytes’ worth of changes, I was able to turn everything red.

The monitor was still confused about the resolution, though, thinking it was 1152×864 when it was really 640×480. You can see in the photo above how the whole image appears twice on the screen. It should be a solid red screen.

After a little quality time with the oscilloscope, I discovered that my HSYNC fix hadn’t fixed anything at all, it had merely broken it in a different way. I reprogrammed the GAL that generates HSYNC, this time fixing the bug for real. Suddenly the monitor started showing pretty much what I expected: a screen full of garbage at 640×480. Success, of a sort.

Now that things were behaving a little more sensibly, I started to worry about those light/dark vertical lines you can see in the image above. That’s not a result of the garbage data in video memory, as the lines extend straight through blocks of solid colors. It’s some kind of electrical noise creeping into the video output. It’s strange, because the lines are very “solid” and consistent, not blurry or wavy or intermittent like I would expect noise to be. I believe the 20MHz pixel clock is somehow leaking into the video output, because when I examined the VGA signal on the oscilloscope, the noise seemed to have have a 20MHz frequency. Maybe not though, because the lines aren’t just simple alternating light and dark bands, but are a repeating series of various lighter and darker vertical lines. So it seems I need some filter capacitors somewhere, or termination resistors, or a voodoo doll or something. Uh, yeah. This is basically why I’m a software guy and not an electrical engineer.

The analog VGA output is generated by a UM70C171 palette chip that I’ve mentioned several times before. I pulled it off an old video card that I dug out of the bottom of a box at Weird Stuff, a Silicon Valley warehouse of electronics junk. At the time I also bought a second old video card that had a chip made by Music Semiconductor, that I guessed was a UM70C171 clone, since its part number included the digits C171, it was the same size and shape, and the video card itself was similar. On a whim, I decided to try swapping in the Music chip, to see if it might be any more noise tolerant than the UM70C171. In retrospect, that was a little dangerous, since I really had no idea if the Music chip was some completely different IC that might fry BMOW when I swapped it in. But I threw caution to the wind, stuck in the mystery Music chip, and turned on the power. To my pleasure, not only did it work, but the noise seemed significantly reduced.

If you click the photo, you can view a larger version where the vertical noise bands are still visible. Areas that should be solid colors have thin vertical lines of varying brightness running through them. I really don’t know what causes this.

I decided to ignore the vertical lines for the moment, and set to work exercising the video modes. It’s funny, after having designed the video system, you’d think I’d know exactly what values to store where in memory to setup a particular mode or draw an image, but really I don’t. The video system schematics just prove that video is theoretically possible, but they don’t directly show you how to do it. It took me quite a while to figure out exactly where the video RAM and control registers mapped into memory, and what values to set in order make the right things happen. Honestly, I’ve only just begun to scratch the surface of it. I guess I need to write myself some documentation or a manual as I go.

Just poking bytes into memory using the monitor program, I was able to get things to happen, but I wasn’t always exactly sure what video mode I was in, or which options were currently enabled. So now I’ve reached the point where I can make things happen on the screen, but I’m not sure they’re quite what’s supposed to be happening. More time reviewing the schematics and GAL equations is needed to decipher it all. Why did I make this thing so darn complicated? I probably should have gone for a single video mode, at a fixed resolution and bit depth, and screw all this flexibility.

Nevertheless, I did get as far as clearing the screen, and turning on a single pixel in the center. I think this was in 128×480 @ 256 colors mode, but I’m not really sure. Help!

Next steps:

  • Figure out what’s going on with those vertical lines, or learn to live with them.
  • Reverse-engineer my own too-complicated design, so I can learn how to use it to create images.
  • It seems as if the image is too dark by about 50%. What should be full white appears medium gray. I need to double-check the signal levels with the oscilloscope: they should be 0.7v for the analog VGA signals.
  • Clearing the screen often causes the monitor to temporarily lose sync. Why? HSYNC and VSYNC should be unaffected by the contents of memory. Maybe some bus noise is causing false triggering of the sync signals?
  • Depending on the method I use to clear the screen, it crashes BMOW. Hopefully that’s just a bug in my clear screen subroutine, and not another noise problem.
  • Once all of the questions above are more or less resolved, I’ll add the character generator ROM so I can print some text.
Read 11 comments and join the conversation 

« Newer PostsOlder Posts »