No longer updated!

My blogspot site is no longer updated. Most of the posts here are archived at along with new content.

Wednesday, 23 April 2003

LED Message board hacking

LED message boards look nice, and are much more eye-catching than a LCD or TFT screen. However, proper message boards are expensive - about £150 - so you’d need a good reason to justify buying one.

Maplin occasionally have ‘toy’ message boards on sale much cheaper - around £25. However, these can only hold a short message and this has to be programmed in via a small built-in keyboard. They are not quite so well built as the proper message boards, and have slightly smaller displays, but apart from that they only differ in terms of control electronics.

Under the hood

Maplin’s message board is called a ‘GM Light’. This produces no useful results in Google, other than lots of pages for GM Light Trucks and a pistol of some sort. However, pulling the device apart reveals some more interesting information. There are eight ICs on board. There are five of one sort, which can be easily identified by the part number printed on them. The relevant code is 74HC574, which identifies it as a latch. Two more are 74HC164, a shift register. The remaining chip is oddly packaged, looking like another piece of PCB with a resin blob in the middle where the chip presumably is. There are no markings on it, so presumably it is an ASIC, and its use will remain a mystery.

By tracing some of the tracks on the board, it’s possible to figure out how the board should work.

How it works

The board is divided horizontally into 4 blocks of 16 columns and one block of 8 columns. One of the latch chips drives each of these blocks. One latch chip drives a whole row in each block. The latch chips all share the same data bus, so the latch clock lines must be triggered individually to load different data into each latch.

The shift registers are joined together so that the highest bit output of one shift register is the data input for the second. This effectively daisy-chains both chips, enabling a bit pattern to propagate through them.

From this information I could figure out one way in which the board could work. This may not be the way the ASIC does it, but that doesn’t matter.

By loading a single pulse into the shift register at a time (i.e. 1 every 16 clock cycles), all the outputs of the shift registers will turn on sequentially. Each output from the shift registers is connected to a transistor which, when on, conducts the cathode of each LED to ground. Consequently, one column in each block is activated on each clock cycle. The inital pulse to the shift registers must be regenerated every sixteen cycles.

The latch chips control the rows, so data loaded into them will control the pattern of LEDs seen in the currently activated column. By loading new data into each latch for each new column, a pattern can be displayed. Note that there is no ‘output enable’ (or at least if there is, we didn’t use it) but the latches can be loaded so quickly that any glitch is invisible.


Obviously we can’t write to the latches or shift registers ourselves while the ASIC is trying to do the same, so the ASIC has to go. A more patient person might use a solder pump or wick to unsolder the ASIC from the motherboard, but I went for the brute force and ignorance approach. I jammed a knife under one end of the ASIC and ran a soldering iron down each side of the chip repeatedly until it came away (it’s effectively surface mounted). Unfortunately, some tracks on the board are routed through pads for the ASIC, and my approach ripped a few tracks up, so I had to patch the PCB back together again. The yellow wire on this photo is one of the patch wires.

Once the ASIC was gone, the remaining rather fiddly job was to attach wires to the appropriate chip pins - 7 to the latch data lines, one to each latch’s clock line, one to the first shift register’s data line, and one to the shift registers’ clock.

It’s then a relatively simple job to hook up all the lines to a PIC16F871. I put all the lines through a 1k resistor to avoid damage due to contention - although all the lines should be inputs to the message board PCB, there might be something else on there driving a line that I hadn’t noticed.


The next step was programming the PIC16F871 to drive the appropriate lines. The code to multiplex the display has to run quickly to maintain a reasonable image, so I allocated a ’screen buffer’ to hold the current pattern for the LEDs. With one byte for each of the five 16-column blocks, this is 80 bytes - a lot for a PIC16F871 which has very limited on-board RAM. This leaves only 16 bytes free in the main page. Actually, the display only uses 7 bits of each byte, and the last half of the fifth byte is invisible (off the edge of the display) but it makes the software much simpler to consider it as an 80*8 bit array. In fact, the eight columns which are invisible are useful - they can be used as an offscreen buffer to download the next character into.

Once the code to display a multiplexed pattern is done, the next stage is to make the pattern change. The two important jobs are to scroll the display (simple) and to insert new characters into the pattern (difficult). Scrolling just involves running through the buffer and copying each location to the location further down. This happens much more slowly than the multiplexing code.

To insert new characters, we need to know what the next character should be, and also what bitmap makes up this character. The font is held in the PIC16F871’s program memory. Program memory is much more plentiful on the 16F871 than RAM, but requires some memory-mapped IO in order to retrieve it. There is a slight time penalty, but this isn’t so important as a new character only needs to be fetched infrequently, with respect to the speed that multiplexing occurs.

Getting all the timing and character downloading right took a long time, but eventually I had a scrolling message on the display. This was the majority of the work for version 1.0.

Version 1.0

Version 1.0 of the message board had a message hard-coded into program memory. I loaded it with an insulting message, and attached the whole board to the back of my combat robot, Cayenne

Unfortunately, I don’t have any pictures of Cayenne with the message board attached. A couple of days later, I took Cayenne to the qualifying sessions for Robot Wars 7. There is never enough time to do what you want at a robot combat event, and taking photos is a fairly low priority. There are, however, several pictures of Cayenne with the bits of the message board that were swept out of the arena after the fight.

Version 1.1

Once my enthusiasm returned, I thought of another use for a message board.

Using several ‘talkers’ (chat rooms) on a laptop with a small display poses a problem - how to keep track of all the messages arriving from several sources at once, especially when you’re working on something that requires the full display. Sure, you can make each terminal beep when it receives a message, but you still don’t know which window it came from, or if it’s important enough to switch away from your main application.

So, why not get all the messages from your talkers displayed on a scrolling LED display? To do this, I added serial communication to the original display, so it would display any text sent to the serial port of a PC. The PIC16F871 has a serial port on board, but it only works on TTL voltage levels. Help comes in the shape of the wonderful MAX232 chip, which generates the +/- 12V required by RS232 from a 5V source.

Serial communications

Cunningly, I initially wired it up in TX-TX and RX-RX configuration. Luckily, I used my £10 laptop for testing and the MAX232 chip didn’t explode, so after a bit of debugging I swapped it for the more conventional TX-RX, RX-TX configuration and connected it to my server. Now, my server could talk to the message board.

I implemented a 16-byte rolling buffer on the 16F871 - the only memory available on the chip - and got it to send XON/XOFF bytes to stop the server sending too much data at once. There were a lot of problems with the buffer - mostly due to my own incompetency, assigning two variables to the same address, and not preserving variables in the serial recieve interrupt routine. Debugging was tricky as Microchip’s MPLAB can’t simulate the serial port. However, after a few irritating nights, the message board worked as planned.

From the talker to the display

In order to use talkers as normal, I use the unix tee command to split off output. For example,

telnet 8080 | tee -a example.log

Then a separate process runs tail -n 0 -f example.log > /dev/ttyS0 - having set up ttyS0 for 300 baud communication with xon/xoff flow control. Why 300 baud? That’s the speed my robots’ radio control system runs at, and I copied the code directly from the receiver. 300 baud is still faster than the message board can cope with.

This displays everything coming through the talker on the message board. Of course, it would be better to filter this. I currently have a sed script to remove ANSI codes, and this could be expanded to check for interesting messages (new message posted, user login etc)