November, 2006

  • Eric Gunnerson's Compendium

    Reading switches from the parallel port


    I've been working on a side project that requires me to sense the state of a few mechanical switches from software, so I've been spending some time working on parallel port programming.

    There are some good resources out there for understanding parallel ports. I've been reading:

    The problem is that parallel ports have been around for a long time, and went through lots of weird permuatations before the IEEE standard was written in 1994. A lot of the information is good, but describes the world as it was 10 years ago, not the way it is now.

    So, there are a few things it's useful to know about today's parallel ports:

    • There are three flavors of parallel ports (and some other variants). SPP, EPP, and ECP. Most systems support all three, but you likely have to set the flavor you want in the BIOS.
    • There is lots of stuff written about doing input using SPP. Some of it uses the status lines as input (5 bits max). Some of it uses behavior that is implementation defined. Some uses extra hardware. The vast majority of it is irrelevant if you can use EPP, so don't spend too much time looking at the SPP docs.
    • You will see discussions about the need for pull-up resisters. I've written a bigger discussion later in this post, but the short form is that most (if not all) printer ports are likely to have built-in pull-up resisters.
    • You can't access the ports directly on NT-based operating systems - you need some sort of driver. I'm using Inpout32.dll for WIN NT/2000/XP .
    • EPP ports aren't automatically configured for input. You need to set bit 5 in the control register (at the base address + 2) to turn it on.

    That aside, onto the fun. But first, a few words of advice.

    Tread lightly, young maker, lest ye mess something up and release the magic smoke in your motherboard.

    Things you'll need:

    • A male DB25 connector that plugs into the parallel port.
    • Some way to connect to the connector. If it's a solder style, you'll need wire (use an old diskette ribbon cable...), solder, and a soldering iron. And a bit of skill.
    • A ohmmeter or some sort of continuity tester. You can build one with a light bulb, a battery, and a wire. If you can't, then maybe you shouldn't be trying this...
    • A switch. Momentary contact, normally open. Or just two bare wires you can touch.
    • Wire. I use patch leads (leads with clips on the end) for trying things out.

    The data lines on the parallel port are lines 2-9, where pin 1 is the top right pin when looking at the connector on the motherboard. If you're younger than I am, you may be able to read the embossed numbers on the male connector.

    The ground lines are pins 18-25, designed on the maxim that you can't have too many grounds. You could also use the computer chassis ground if it's more convenient.

    So, hook one side of your switch to pin 2 (data line 0) and the other to one of the ground pins (surprise me!). Inspect your work to make sure you haven't bridged any pins, and hook your continuity tester to the pins on the connector to make sure pressing the switch completes a circuit between those pins.

    Preparing the computer

    So, you need to set your port to EPP in the BIOS, download inpout32, and start up your favorite development environment. If you're using C#, you can find some info on using inpout32 through PInvoke here. You'll need to add the appropriate definition for the In32 method.

    Oh, and plug the connector in with your computer turned off.

    Writing the code

    The code basically looks like this:

    const int LPT1BASE = 0x378;

    Out32(LPT1BASE + 2, 0x20);

    int lastData = 255;

    while (true)
        int data = In32(LPT1BASE);
        if (data != 255 && data != lastData)
            // do something - print it out of something
        lastData = data;

    Pretty tough, huh? When you run this and press the button, data should be 254 if you wired things up. If it doesn't, go back and check your wiring, your parallel port setting, etc.

    You may have figured out that this approach uses polling. Yes, it does, and that means it consumes a bit of CPU on an ongoing basis. If I've read the docs correctly, there are ways to make this interrupt-based, with some more external hardware and a lot more code. You are welcome to spend time on that, but given the current state of the art, at that point it's less hassle to program a microcontroller that speaks serial or even USB.

    That's it. And now for a brief aside.


    You may have asked yourself, "why does connect something to ground turn it on, and is a pull-up resistor related to high school gym class?"

    But that will take a bit of history. Ancient history. Even before *I* was born history.

    Way back in 1962, Texas instruments introduced the TTL logic family, forever enshrining the +5V power supply in the world of computers and electronics.

    Because of the characterstics of the TTL circuit design, a TTL output held at high can only source about 0.4 mA of current. That's not much. A TTL output held low, however, can source something like 15 mA of current. That makes it preferable to sink current rather than source it.

    (those with a big electronics background are probably cringing at the simplification here. Feel free to comment...)

    There's also another problem that comes up related to interfacing. Say that you wanted to hook up a TTL output to a system that uses 12V to switch a relay. You need an output that only goes from 0V to 12V, but the TTL "high" output is only 5V (it actually isn't - it's more like 3 volts).

    So, what you do is, you use what is called an open collector design output. The output can either be low (pulled to ground), or a floating state. You attach a resistor between your 12V source and the output, and this resistor "pulls up" the floating state up to 12V.

    You also use this sort of thing when you want to drive a bus - you can let the output float with the bus most of the time, and then switch in the pull-up when you need it (real buses use different techniques, but you get the idea). Pull ups are a simple way to get what you want, but use up power and aren't terribly fast. But this was the early 60s, after all...

    How does this relate to parallel ports? Well, the data pins on the ports are two-way, and early ports didn't provide pull-ups, so you would need to add them yourselves.

    Oh, and one final question. Why do parallel ports use 1960s technology?

    Well, TTL logic has problems, because it's bipolar transistor-based (the Ts in TTL), it's pretty tolerant of static and therefore a good choice for a bus line. You could do something similar in CMOS but you'd have to put a lot more effort into input protection. There are logic families that look like TTL but are CMOS inside, and I suspect that most parallel ports these days take that approach.


  • Eric Gunnerson's Compendium

    Custom Music System Case mod


    Early this summer, the music PC at my ski place was "borrowed" by an unexpected visitor. So, I decided to build a replacement.

    The system used a micro-atx board in a small pc chassis. It worked fine, but the appearance was - well, it looked like a small cheap black PC case. There are cases designed to look like components, but they're $$$. While I was casting around for ideas, I noticed the broken Pioneer Elite DVD carousel player sitting underneath my workbench. Hmm...

    And so, my first casemod was born.

    The first step was to rip out all the guts. Unlike most DVD players - which these days are constructed mostly of air - this one had a lot of components. The internals were nicely designed, but there was one curious feature. Attached to the bottom of the unit was a 1/16th inch steel plate. The "make it worth the money" plate that differentiates the Elite series players from the others.

    Okay, to be fair, the electronics are better as well, but they don't weigh much more than the cheap ones.

    Once I got it ripped apart, I had to order up some components. Off to newegg I went, and picked up the following:

    • Duron 1.6 GHz
    • 256M Memory (Kingston)
    • Atrix 200W Power supply (quiet...)
    • Masscool cpu fan (also quiet...)
    • BIOSTAR M7VIG400 motherboard

    The total price was $245.58, including shipping.

    After they showed up, I realized that I forgot a DVD drive, so I picked up a cheap one locally.

    I then had to try to fit them into the case. One of the advantages of using a big carousel player is that there is a fair bit of room. I could easily fit the motherboard and power supply side by side, which left room for the disk drive. After some thought, I realized that I didn't really need a DVD drive after I put windows on the system, and decided not to mount one in the case.

    Then I ran into the first problem. The bottom of the dvd player chassis has a lot of indentations to fit the internal components in, but nothing lined up with the motherboard screw locations. What I needed was a flat piece of metal to use as a motherboard tray. Something the same size as the chassis.

    Something like the "make it feel expensive" plate. Which, amazingly, slid right into the chassis perfectly.

    I attached the headers to the motherboard and made a template of their locations out of paper. I punched holes in the paper with a punch, and then marked the exact locations of the holes on the paper. Attached the paper to the plate, marked the holes, drilled them, and then tapped them (#6-32). I tapped some headers into the chassis, and used that to attach the plate to the chassis.

    Next was cutting out the holes in the back of the chassis for the motherboard plate, and holes and screws for the power supply.

    Finally, I drilled mounting holes in the side of the chassis to mount the disk drive, and made a plate to mount the other side of the disk to the motherboard plate.

    Here's what the layout looks like:

    and here's a picture from the back:

    The next problem was how to control the music player. The software that I wrote supports control through its UI, through a web interface, and through an infrared remote control. I could have done the second or the third, but there were some nice panel buttons on the DVD player.

    Which explain my parallel port article.

    I took the front panel off and did a lot of tracing, and then hooked up the points that I needed to a ribbon cable. The points I hooked up were:

    • Power LED + and -
    • Disk mode + and -
    • Ground
    • Power switch
    • Disk change
    • Play
    • Pause
    • Next Track
    • Previous Track

    The first four are connected to headers that hook up to the motherboard, and the last 5 are connected to the parallel port connector you can see in the photos. I considered soldering the wires directly to the inside side of the connector, but decided not to mod the motherboard.

    Then, it was putting Windows on, copying over my MP3 collection, and doing a small modification to my player software to support the parallel port. The software autoplays on startup, and I enabled remote desktop so that I could use it without the monitor/keyboard/mouse.

    Here's the front view. When I bought the player, blue LEDs were new, which is why the power led is blue.


  • Eric Gunnerson's Compendium

    Obvious news story of the day...


    More indication that there isn't 24 hours worth of news out there. Today while I was working out I looked at CNN, and saw:

    Developing Story

    Colorado mountain communities expect two feet of snow.


Page 1 of 1 (3 items)