Making a cool LED "VU meter" for your PC

Introduction

This article describes a simple, utterly useless, but extremely cool LED-based VU meter I made for my PC. I'll provide every detail I can think of, so that you can easily make one yourself.

Check out this small video of the finished UV meter in action (~5.1mb).

Overview

My VU meter hack is part hardware, part software. In fact, I'm a software person myself, so I kept the hardware extremely simple, and moved all the complexity software-side.

The hardware part is just an array of 6 LEDs connected to the first 6 data pins of the PC parallel port.

The software I've written to drive those LEDs runs on GNU/Linux, and consists of three parts:

Making the Hardware

Connecting the LEDs to the parallel port is pretty straightforward. I used a regular printer cable, and a centronics female connector I bought from an electronics shop. Then you can just solder the cables that will go to the LEDs directly onto the connector. However my connector has a nice feature, it just clamps onto a standard ribbon cable (like the floppy or ATA cables). Thus I could use the convenient floppy female connector to plug in my LED cables without soldering anything (see picture).

LED array on the breadboard

As you can see in the picture, I made the whole thing on a breadboard to keep all the components easily reusable. I'm too lazy to go buy new components when I need them, so I generally avoid soldering stuff if I can help it.

Each LED anode is connected to the corresponding data pin through a 1 kOhm resistor. This is very important, to avoid drawing too much current from the parallel port, which can easily fry the port chip. Also, LED longevity is slashed down considerably if you put too much current through them.

Writing the Software

The way I eventually implemented the software part of this system can easily be considered overengineered for the scope of a simple xmms controlled VU meter. However the VU meter was actually an afterthought, on what would be cool to do with my LED controlling daemon that was already done at that point :)

The decision to write a LED controlling daemon was influenced by two facts. First of all, the LED device is a single shared resource. And as such a degree of coordination is needed. If multiple programs tried to use the LEDs at the same time, the result would be meaningless.

However, that problem alone could be solved in a much simpler way. through lock files for instance. What makes the daemon-based implementation infinitely more compelling, is that in order for an application to open the parallel port for writing, it must be running as root. So, instead of having every random program that might want access to the LEDs running as root, which for the security-illiterate amongst you, is simply unacceptable, the compromise is to have only one, hopefully bug-free and secure program do that.

The parled Daemon and libpled

As was mentioned above, the parled daemon must be run as root, in order to be able to open the parallel port for writing (through the call to pin_init_user of the parapin library). However, after that is taken care of, there is no reason at all to continue running as root. So, in order to minimize any security risks, after initialization but before starting to accept any connections, parled drops superuser priviledges and becomes the user specified through the -u argument ("nobody" is a good choice).

Parled listens for both local or remote connections, through internet and unix domain sockets. It listens for TCP/IP connections on the port "0x1edd" (7901), and for local connections through the "/tmp/parled.sock" socket.

A client program who wishes to connect to the daemon, calls pled_connect of the libpled library, supplying as arguments an address string and a port number for TCP/IP connections, or both zeros for local UNIX domain connections.

Upon connection, a client implicitly requests immediate control of the LEDs. If this cannot be satisfied by the daemon, an error code, signified by a single minus character is received and the connection is closed. In contrast, if the request succeeds, a plus character is reveived, and the daemon enters a loop executing client commands for changing the LED bits.