Programable LED Signs / Name Badges
I wanted to implement an auxiliary external display on Linux. I looked at a few displays and found three that had reasonable prices. Unfortunately none of them came with open source software, they did however come with some working but pretty poor windows software. So to use these devices from Linux or any other OS in a specialized way, I would have to reverse engineer the signs to a certain extent. This page is basically a summary on how I reverse engineered the communication protocols for the three signs.
I have not worked on this project in a long time, never completely finished the third sign's writeup. I may finish it up if there is interest as I have the analysis written down in notes and a few files. I never wrote any programming in linux to control the signs. I was planning on using python, and I think it would be very easy to do anyway, I currently don't have the need or time to write the code.
portmon.exe a tool made by SysInternals(now Microsoft) that monitors serial port communications, I haven't found an equivalent tool in Linux yet.
Details of sign will follow this general layout:
The grid paper's major line interval is 1 cm and the minor line interval is 1 mm.
Made in China
The Microprocessor is an STC 89C51RC, 40C-LQFP44 with a 22.1184MHz crystal. Which is an 8bit micro with a 32kByte Flash. I couldn't find any data sheets in english on the STC part. I suspect it is a Chinese clone of the Atmel AT89C51RC. The pins don't exactly match but they look to be very close. To multiplex the uC's outputs the sign uses two NXP 74HC595D 8-bit serial-in, serial or parallel-out shift register with output latches.
Each row of LEDs are connected together, then connected to a 470 ohm resistor which is tied to VCC, in addition """"""it may be connected to a pin of the micro. Each column of LEDs is tied together then tied to one of the microprocessor's pins or one of the shift registers' pins.
To program the sign, you use the DB9-F to USB Mini-B cable, and to charge/run it you either hook it up to a USB port, or connect the 120V to 5V wall wart that has a USB Mini-B connector.
The programming cable is very simple, it uses pins 2,3,4,5 on the DB9. Pin 5 (GND) is the serial port's ground pin, this connects to a red wire which runs to pin 5 on the USB connector. Pin 4 (DTR) on the DB9 connects to Pin 2 (RXD) on the DB9 via a 20K0 +/-1% ohms 1/8 watt resistor (Red-Black-Black-Red-Brown). Pin 3 (TXD) on the DB9 connects to a white wire which runs to pin 3 on the USB connector. Pin 2 (RXD) on the DB9 connects to a green wire which runs to pin 2 on the USB connector. When programming the display power is provided by the internal Lithium Ion battery pack. When using the wall-wart power supply, power is provided by pin 1 on the usb connector.
I sent all possible characters, and found the following character set. See messagelink.xls
I'm not sure what values above 0x3B would display or do. I suspect sending values above 0x3B may brick the sign, display additional characters possibly asian, enter a rom programming mode, etc...
Syncs via a serial to IR adapter, the serial port drivers are the same as the other devices.
1x CR2032 battery
The programming interface is done via an unidirectional IR(InfraRed) serial link.
6x NXP 74HC595D, l709K109, UAG0736D
This sign is physically sized between the other two signs, but has the largest LED array, and the most complex feature set.
Looks like there is a programming header for the ATMEGA88, Vdd, Vss and connections to two uC pins
each column of LEDs' anode/cathode is connected together, and each column is then connected to one of the Q ports on the 74HC959D's
6 messages of 250characters each for a total of 1500 characters message space
Assuming 6 messages of 250chars and 2 images 12x1024pixels are sent:
After the first byte (0x00) the software sends the
After the command/address is sent, the data and settings part of the data group is sent, it always consists of 64 bytes. If a particular group doesn't have enough data to pack the entire 64byte block it is zero padded. If a particular group has more than 64 bytes it's wrapped into the next data group. If a message is set, 4 data groups are sent for each message. However, text message can only be 250 characters, the maximum number of data blocks is 4 or 256 bytes, the "extra" 6 bytes are used as follows. The first 4 bytes in the first data group of each message provide the Speed setting, Message number, Style setting and message length. The last two bytes of the last data group of each message are always 0x00 and 0x00, I'd guess the designer(s) padded out these last bytes to make the maximum message length a nice round number, 250. These 250 bytes store the message, using english character set, it's one byte for one character. The asian character sets require two bytes per character.
--------------------character set image---------------
Once the data and settings are sent, a check sum is sent. The checksum is easily calculated by adding up the last three bytes of the command/address data and the 64 byte data/settings part. The resulting sum is taken mod 256 to return an 1 byte number. It took me a while to figure out this check sum. Initially I thought it was a sum, however when I added up all of the bytes in a block I didn't get the correct number. Graphing the checksum values showed an obvious cyclic pattern, so this would probably throw out something complicated like a CRC, plus a CRC wouldn't really be nessary for a simple short serial link, also CRC would eat up too many resources to be of much benifit. Additional clues were if any byte in the message changed the check sum would change, if the address changed the checksum changed. At one point I thought it might be doing an XOR of all the bytes so I fiddled around with calculating XORs in excel but that didn't give the correct result either. I went back to looking at sums again since there was such an obvious pattern. When I summed the message bytes I noticed that the sum (0x89_would be close to the check sum (0x87) then it hit me, exclude the first byte 0x02 from the checksum, and voila it worked for every data group I had captured!
-------picture of cyclic checksum value graph-------
The data format for images was also an interesting challenge. It was fairly obvious which data groups were being used for images by sending known images, ie all black, or only first and last pixel black, etc... However the device was sending more data than was needed. For a 12x1024 pixel or 12,288 bit image, it was sending 31 groups of 64 bytes and one group of 56 bytes or 2040 bytes 16,320 bits of image data. By sending a couple specially crafted images I was able to figure out how it was sending the data.
Image message settings and their address blocks, are they addresses?