BMOW title
Floppy Emu banner

Peripherals Galore

There’s been lots of recent activity on different fronts. Too bad I still haven’t made any progress actually building the machine.

Keyboardin’ Part 2

keyboard connector

Here’s a shot of my glorious hand-wired PS/2 keyboard connector. I spent some time over the weekend working out the details of how to read keyboard data. I came up with a solution that uses a 74LS161 to count the incoming bits, and a GAL to shift the bits into a byte, and signal a CPU interrupt once all the bytes have been read. It should be pretty simple to use in practice. At first I was worried that my CPU wouldn’t be able to process interrupts from the keyboard quickly enough, and I’d need to implement some kind of queue for incoming keyboard bytes. After doing some testing, though, it turns out that there’s always at least 3 milliseconds between bytes, even for the bytes in a multi-byte scan code for a single keypress. That’s an eternity in computing terms.

Keeping It Real-Time

I ordered a Texas Instruments real-time clock from a parts supplier, and updated my design to incorporate it. Unlike most RTC’s I’ve seen that use the same pins for address and data (is this how “real” PC’s work?), this one has separate pins, and can be accessed just like a 16-byte RAM. It also has an integrated timer crystal and battery. Getting the current date and time is as easy as reading from a particular memory address. The RTC can also be configured to generate a periodic interrupt at intervals between 30 microseconds and 500 milliseconds, or at a specific future time.

Embiggen My LCD

LCDs

I got a new 20×4 LCD panel to replace my old 16×2 one. The photo above shows their relative sizes. Conveniently, the new LCD uses the same controller chip as the old one, so I was able to drop it into my existing “Hello World” circuit, and get it to print text on the LCD immediately. The LCD display panel’s height is almost exactly the same as a 5 1/4″ drive bay opening on a standard PC case.

On the Case

BMOW case

I decided to give up on the idea of building a custom case for BMOW. I’m having enough trouble getting motivated to build the machine itself, so I don’t need a case construction project too. I bought a standard PC case from Apevia, with clear side panels so that everyone can see my awesome hand-wired circuitry inside. The LCD should fit nicely in the lower of the two 5 1/4″ drive bays, and I can use the existing USB connector and power supply… sort of.

If you stop to consider how your PC is able to turn itself off from software, then you realize there must be something special going on with the power supply. It turns out that for a standard ATX power supply, there are some pins on the motherboard connector that a normal PC uses to tell the power supply when to turn on and off. The power button on the front of the case is connected to the motherboard, not the power supply. This means that if you don’t have a standard PC motherboard, you can’t actually turn on the power supply! This was a problem I hadn’t expected.

power supply

After some research, I learned that by inserting a jumper wire between two pins on the ATX motherboard connector, I could simulate the signal that a PC motherboard sends to turn on the power supply. It seems a little ugly and potentially dangerous, since connecting to the wrong pin could bridge different voltage outputs, or short power to ground, probably killing the PSU. Did you know that a standard PC power supply puts out 6 different voltages? +5v, -5v, +12v, -12v, +3.3v, and +5v standby circuit. On mine, several of these outputs can drive over 20 amps, which is enough to do some damage if I screw up the wiring. Nevertheless, I popped in the jumper wire, and it worked flawlessly. Above is a photo of my handiwork: a green jumper wire sticking out of the ATX connector above the PSU.

Beep Beep Beep

Like all PC cases, this one has a two wire speaker that’s normally used to make a “beep” at boot-up, and that’s all. I was curious how it worked. Did applying a voltage across the two speaker leads make it play a fixed frequency tone, or could I play any frequency tone by applying a varying voltage to the leads? It turned out that the speaker can play any frequency, with an appropriate input. This opens up a lot of interesting possibilities. By connecting just two more wires to my CPU, I can play arbitrary sounds!

The simplest approach would be to have the CPU set a speaker value in a dedicated audio register, which would be turned into an appropriate speaker voltage by a D-to-A converter. To play a sound, the CPU would need to quickly and continuously change the value in the speaker register, to create an output waveform. I don’t think BMOW will be fast enough to make this really practical, though. Assuming a modest 10kHz sampling rate for audio waveforms, and a 3MHz CPU speed, there would be only 300 clock cycles between each required update of the speaker register. That probably wouldn’t leave the CPU enough time to do anything interesting besides sitting in a busy loop, playing back a waveform.

A more realistic idea would be to have the CPU write the desired tone frequency to a speaker register, and then use dedicated hardware to generate a square or sine wave at that frequency. This would require very little CPU time, although the type of audio it could generate would be fairly primitive. Still, since this is a computing project and not an audio one, it seems like the best approach. I haven’t worked out the details yet, but I will probably divide the system clock down to about 10kHz, and then use the speaker register’s value to divide it down further by a variable amount, to produce different frequencies in the audible range. If I want to get fancy, I may also add volume or envelope control. I need to find a reasonable compromise between design complexity (not to mention part count) and the quality of sound I can generate.

Video Madness

test pattern

After all this, I realized that I now had the makings of keyboard input, a nice case, and even audio output. All I was missing was video output to make a “real” computer, and ditch the USB link to a PC entirely. With that goal in mind, I started to research what it would take to generate NTSC or VGA video output from BMOW.

In short, while it would be complicated, I believe video output is within reach if I want to spend the time to do it. It’s silly, but video generation feels a little like the holy grail of computer design to me. Back in college, I actually built a primitive video game with NTSC output, and I still have all the circuit schematics. The video generator chip I used is now obsolete, sadly, and I couldn’t find any replacement. But as the number of devices I own that will display a composite video signal dwindles, it probably makes more sense to pursue VGA output rather than NTSC anyway. My investigations suggest that it’s about the same difficulty either way.

From what I can tell, there are five signals on the VGA connector that I would need to care about: horizontal sync, vertical sync, and red, green, and blue data. HSync and VSync are basically just square waves with non-uniform duty cycles, used to signal the start of a new line or a new frame. It shouldn’t be too hard to build a circuit using some counters to generate those signals, I hope, or I believe there are also single-chip solutions that generate the necessary sync signals. Then the three color signals are continuously varying analog voltages (between 0 and 0.7v, I think) during a portion of time between hsyncs. For a 640×480 output, the visible portion of each scan line takes about 25 us, or about 40 ns per pixel. A D-to-A converter could be used to generate the desired voltage output by reading a byte from a RAM every 40 ns, and converting it to color voltages.

After reading the VGA specs, I think it would be relatively straightforward to build a circuit to output a fixed VGA signal, in some kind of test pattern. While it certainly wouldn’t be a piece of cake, it would be just a matter of generating the appropriate sync and data signals. What seems much more complicated to me is sharing video memory between the video output circuit and the CPU. The video output circuit would always be reading successive bytes from the video RAM. So what happens when the CPU wants to write data to video memory? I can think of a few possible solutions, none of which seem great:

  1. The CPU takes priority over the video output circuit, pre-empting it. Some kind of video garbage gets rendered very briefly if this happens during the visible portion of the VGA screen refresh.
  2. The CPU waits until a horizontal or vertical blanking interval, and then writes its data. This would avoid video garbage being drawn, but stalls the CPU, and requires implementing some way for the CPU to query the video circuitry state.
  3. The CPU writes data to a video input FIFO instead of directly to video memory, and the video circuitry drains the FIFO during the idle of blanking intervals. This would work well, I think, but would be complex to implement. The CPU would still have to check to make sure the FIFO wasn’t full before writing new data.
  4. The video circuitry stores data in a video output FIFO, rather than transferring data from video memory directory to the D-to-A converter. This would be very similar to the previous approach, although perhaps slightly easier to implement, since it would only need to queue data values and not addresses.

I’m going to postpone any further work on video generation for the time being, although it does seem tantalizing.

Read 5 comments and join the conversation 

5 Comments so far

  1. Hamsterman - March 2nd, 2008 12:21 pm

    Chances are you already know this, but it might be useful to someone else reading this:

    You could probably find an old AT power supply on ebay for next to nothing. I bought four old Pentiums and a 486 last year, and they all have working AT power supplies. These switch on with a conventional ON/OFF switch (no control from the motherboard), and deliver +5V, -5V, +12V and -12V.

    Also take note that it is possible to damage a computer power supply if you turn it on without connecting it to some form of load. Connecting it to a CD-ROM or a HDD should (though I may be mistaken) be adequate to prevent damage.

  2. Steve - March 2nd, 2008 11:05 pm

    Good suggestion on the old non-ATX power supplies, Hamsterman.

    I was about to say that I can’t imagine how having no load could be a problem, but I did a little research, and you’re right. I’m not clear exactly why, but something about the way PC supplies are typically built requires a minimum amount of current to be flowing through a load in order for it to work properly. Some PSUs have load resistors internally to accomplish this, but others may not. In that case you’d need a resistor (of an appropriate resistance and power rating) between power and ground on each PSU output, or some “dummy” PC components like you suggested. My impression is that if the load requirements aren’t met, the PSU’s voltage outputs might not be at the rated voltages, or it might just fail to turn on at all, but it wouldn’t damage anything.

    In my ignorance, I tested my PSU with no load, and measured 5.01v at the 5v output. So apparently it either has internal load resistors, or the case fans are enough load.

  3. Brandon - April 6th, 2008 5:34 pm

    Just a thought, you could build a square wave generator with the 74xx14 series. Robot Building for Intermediates by David Cook showed this to build a perfect 38kHz wave for an Infrared Emitter. I’m sure somehow, you could alter this with the CPU to generate sound. The frequency is altered with a variable resistor for the original, just to maybe help you out. As far as video, why not have a “Dual-Buffer” Type system? May not work, but just a random thought I had. Have one RAM for the CPU to write to, and One RAM for the Monitor to take from. Than at a certain interval, just dump over the stuff from the first? I think this is built with an Edge-Triggered Latch Flip-Flop. http://cpuville.4t.com/register.htm I’m pretty new, so this may not work, but just a thought.

  4. Peter Lund - June 10th, 2009 12:24 pm

    The PC has both direct on-off control of the speaker and a keep-playing-this-frequency mode. The latter uses one of the timers in the CTC chip and the former uses one of the output bits of a PIO chip. Another bit from the PIO chip switches between the two modes. The whole thing is glued together with a couple of gates.

  5. Peter Lund - June 10th, 2009 12:30 pm

    As for the video, shouldn’t you be able to get quite far with a single-byte write buffer (that also buffers the destination address, of course) and CPU support for wait states? If the write buffer is full, the CPU stalls. If the write buffer is not full then it accepts the write. As soon as the scanout is not hogging the video RAM, the byte gets written. You probably don’t have to make the world’s fastest implementation so you can cut down on the implementation complexity by making it switch between accepting data from the CPU and writing to the video RAM in different cycles (you don’t need to support write-through if the buffer is empty). By adding an extra cycle here and there you should even be able to span two different clock domains without too much trouble.

Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.