Archive for the 'BMOW 1' Category
Board Layout
While updating the BMOW documentation, I came across this diagram of the main system board layout that might be interesting to share. It shows every part on the board, and howthey’re all grouped into the subsystems that form the computer. Related parts are adjacent most of the time, but I did make some blunders.
Compare the diagram with the photo, and click either one to see a higher-resolution version. They match exactly, except for RAM1 (lower-right of the diagram), which I never got around to placing on the main board.
The core systems which form BMOW’s custom CPU are in the center of the board, shown in light blue, pink, orange, and purple. The rest of the systems are arrayed around the outside.
- Control (light blue): Here’s where the control signals are generated to enable and coordinate everything else. It includes the three microcode ROMs, opcode register, instruction phase counter, and related demultiplexers.
- ALU (pink): The mathematical and logical functions are all performed here. It’s a bit of glue circuitry along with a pair of 74LS181s.
- Address Registers (purple): The program counter, stack pointer, and scratch address register are all 24 bits wide.
- Data Registers (orange): There are three user-visible 8-bit registers named A, X, and Y. A fourth register named T is used internally by the microcode.
- System Clock (light green): An 8MHz oscillator is used along with some flip-flops to generate two 2MHz clocks, one 90 degrees out of phase with the other. The power-on reset circuit is also part of this subsystem.
- Memory (gray): The system has 512K ROM, 512K RAM, and the address decoder. I originally planned for two RAM chips and a total of 1MB of RAM, but later decided that was overkill.
- Devices (dark olive): External hardware is mapped into the CPU’s address space. There’s a real time clock, and interfaces for USB, the keyboard, and the LCD front panel.
- Discrete (dark blue): I lumped together all the miscellaneous resistors and capacitors that were needed into a single component carrier.
- Video (tan): Four GALs serve as row and column counters to generate sequential video memory addresses during the display of each video frame. There’s 32K of VRAM, and a separate 2K character generator ROM. A palette chip pulled from an ancient video card translates VRAM values for each pixel into analog R, G, and B voltages for the monitor. There’s also some demultiplexing circuitry to let the VRAM address bus be driven by the row/column counters or by the CPU address bus. The video system has its own clock, which runs at 25.175MHz.
- Audio (red): Some support chips and an AY-3-8913 programmable sound generator create three voices of modified square wave goodness. The three analog voltages for the voices are generated on-board, but the stereo mixing and amplification are done on a small daughter board.
Date and Time
I’ve written one more program for BMOW: a utility to set the date and time. OK, I admit it’s not very exciting, but it is mighty useful when a buggy program overwrites the memory-mapped real-time clock registers for the fifth time. It also shows the time incrementing as you sit idle at the setting screen, demonstrating that the machine hasn’t crashed.
This will become part of the standard suite of ROM-based demo programs for BMOW. Speaking of which, I’ve put together the final menu of programs for the demo ROM (all of which have been discussed here before), and it totals 403923 bytes. That’s a bit of a problem, since I only have a bit less than 131072 bytes (128K) available.
I’m planning to compress the programs using a 6502-based LZW decompression routine. Compressed, the demo programs require only 124371 bytes, which should leave just enough space for the decompression routine, and a few last-minute odds and ends. I still need to work out the details of the decompressor, but I hope to have that wrapped up later this week.
Once that’s done, I still need to do one last pass through the BMOW schematics and documentation. Much of what’s posted online is out of date, and even what I’ve got here on my PC doesn’t reflect the true state of the hardware in some cases. I need to document it all before I forget everything, and post the updated docs back here for the curious. With that, I’ll be ready to call BMOW done. Maybe I’ll try to arrange a demo party for anyone in the San Francisco area who’s interested.
Lots of ideas have been swirling in my head for my Next Big Project, and I think it’s going to be pretty cool, but I’m forcing myself to hold off on it until BMOW is completed. I only have enough time and energy for one crazy electronics project at a time. BMOW’s almost at the finish line, though, and I’ll definitely be writing more about NBP here soon.
Read 6 comments and join the conversationMusic Visualizer
One more demo: I wrote a music visualizer to show off the AY chip tunes, and also converted a bunch more AY songs for use with BMOW. Now there’s something cool to look at while you listen to that glorious 8-bit music!
The visualizer shows blue, yellow, and green bars for the three voices of the AY-3-8913. The bar’s horizontal position shows the voice’s frequency, and the bar’s height shows the amplitude. The fourteen hex numbers at the bottom are the real-time values of the AY control registers.
The Agent X II track that I used in my first audio demo shows this off pretty well. You can easily pick out which instrument is which voice, and see some of the auditory tricks used, just by watching the visualizer.
Here’s another AY tune running with the visualizer. This one’s called “Power M”, and was evidently written by a guy on speed. Just try to follow the voices! It’s all a blur. Forget it.
Incidentally, this is also the first BMOW demo to show any kind of animation, tame as it is.
Read 6 comments and join the conversationSpit and Polish
I know I’ve said this before, but I think BMOW is fast approaching a state of “done”. For the last week I’ve been polishing some old demos and making some new ones, for inclusion in the final demo ROM. Along the way, I also added a proper startup sound. Turn the machine on, and it announces itself to the world, loud and proud.
I also revisited the video hardware, and created a couple of new demos showing “new” video modes. These modes aren’t really new, of course. The hardware capability was always there, and I knew the modes were theoretically possible, but I’d never before actually taken the time to determine the necessary combination of register settings and video data interleaving to draw an image in every mode. My first target was the highest resolution mode possible for BMOW’s video system: 512×480, with two colors. It is truly any two colors, and not black and white, as this brown and tan Aztec Sun Stone image shows. Click the image to see a full-size version with greater detail.
I then created a second demo that makes use of mixed mode, with the screen split into three regions in 2 bits-per-pixel, 4 bits-per-pixel, and 8 bits-per-pixel modes. The same image of a flowering hedge is shown in all three regions, to demonstrate how the BMOW hardware trades color depth for horizontal resolution.
The 2bpp sample was a bit of a challenge, and was another mode I’d never actually tried before. It turned out that my image editor (GIMP) doesn’t really output 2bpp images, with 4 pixels packed per byte. Instead, it outputs an image in 4bpp format, that just happens to have only 4 colors in its palette instead of 16. Rather than hack the image data, I wrote a BMOW conversion routine to repack the 2bpp image data before it’s displayed.
The screenshot below shows the comparison of the three color depths, but to really appreciate the differences, click the image to see a higher-res screenshot. The 256 color region has rich, green, shiny leaves and a buttery yellow flower, but looks like a mosaic due to the low resolution. The 16 color region holds up well, given that most of the image is green anyway, but the flower becomes a solid yellow region. The flower turns green in the 4 color region, but thanks to the higher resolution and effective dithering, the leaves don’t look too bad.
If I’d chosen an image with a greater variety of colors, the discrepancy between the three would have been much more obvious. A grayscale palette test might be interesting too.
Read 1 comment and join the conversationPhantom Reads
I discovered an interesting BMOW hardware bug today– one that I’m amazed I never noticed before. It involves what I call “phantom reads” causing unexpected system behavior. I only stumbled across the problem by accident, while trying to troubleshoot why the audio system didn’t work in certain circumstances.
In brief, a phantom read operation is being performed on every cycle that memory isn’t explicitly written or read, and the result is thrown away. 99% of the time this is unimportant, because reading from memory or a device doesn’t have any side-effects. Except, in a few cases reads do have side-effects, and bad things happen due to phantom reads.
Every BMOW clock cycle, the CPU will be doing one of three operations:
- reading from memory into a register
- writing from a register into memory
- moving data from one register to another
Memory and registers are on separate busses, connected by a bidirectional bus driver. For reads and writes, the CPU sets the required direction for the bus driver, and puts the desired address on the address bus, activating the needed memory chip or device. But what happens during register-to-register transfers? The bus driver is disabled, completely isolating the register bus from the memory bus. But some value will still be on the address bus, selecting a memory chip or device. What? I had to dig through the schematics and microcode to find the answer.
It turns out that during register-to-register transfers, the address bus will contain whatever’s in the general-purpose address register. Most of the time this will be the address of the most-recently referenced memory location, but because of the way the microcode works, it will sometimes be a combination of bytes from previous addresses and microcode temporary values. So in effect, during register-to-register transfers, a semi-random memory location ends up being read, and the result thrown away. This causes problems in two ways:
- Interrupt flags for the keyboard, USB, and real-time clock are cleared as a side-effect when they are read. Normally this is a good thing, but a phantom read to one of these locations will clear the interrupt flag without ever servicing the interrupt.
- Some write-only devices (audio, LCD, video registers) don’t actually distinguish between reads and writes, and perform a write whenever they’re accessed. I made the assumption that the software would only ever write to these locations, so I saved one wire by not bothering to connect the READ/WRITE line. A phantom read to one of these locations will perform a spurious write. Yikes!
So how can I fix this? At this point, I’m planning to leave the hardware as-is, and try to work-around it in software. Now that I know what to look for, I can predict what types of accesses are likely to cause problematic phantom reads, and avoid them by modifying the code slightly. I was able to do this fairly easily to solve the audio problem that led to this discovery in the first place. I’ll apply the same reasoning to some of the code where I’ve experienced intermittent crashes, and see what I can find.
If I had it all to do over again, I’d probably add a new control line from the CPU called MEMORY_ACCESS or something, that was asserted during any read or write operation. Then the address decoding logic could use that to disable all memory and devices when needed, making a clear distinction between intentional reads and phantom reads.
Read 8 comments and join the conversationBoot Menu 1.0
I’ve implemented the new memory map I described earlier, updated the software, and everything’s working great. This has allowed me to finally make some progress on my goal of a menu-driven bootloader, with a catalog of built-in demo programs from the expanded ROM space. Here’s a screenshot of an early version of the new bootloader, with a couple of demos installed:
On the whole, it works great, and I’m very happy with it. After selecting a built-in demo option, the selected program starts in about a second. Next, I’d like to expand on the bootloader menu concept a bit further.
- Add a power-up sound, along the lines of the Amiga or Mac.
- Design a better logo.
- Dress up the boot screen with some more interesting graphics– a spinning box maybe? That’s an awful lot of plain text up there, and is kind of intimidating. Maybe you should have to press F8 to reveal “advanced boot options” like Windows.
- Create a good video demo. Microchess is the only program that shows anything halfway-interesting graphically.
Not unexpectedly, there are also a pile of small problems to work through:
- With the new bootloader, when BMOW has been turned off for several hours, it almost always crashes on bootup while drawing the BMOW logo. If I press the reset switch, it crashes again. After four or five resets, it works OK, and continues to work until the next lengthy shutdown. Sounds like the program is relying on uninitialized memory somewhere.
- About one time in ten, it will crash while downloading a new program image with the bootloader. I think this is related to a feature I added to show the percent complete on the LCD during download.
- All the demos I want to include won’t fit in 128K. The audio demo alone is 64K. I need to implement some kind of uncompression routine to extract compressed demos from ROM.
- After booting a demo program, the first keypress will not be recognized. After that, keyboard input works fine.
- There’s major video noise when navigating the boot menu. I need to delay the screen updates until the VBLANK period.