Sunday, January 31, 2010

im-me LCD Interface Hacked

Good news everyone, I've reverse engineered the im-me's LCD Display interface and now have working code it drive it. Here's a photo showing a variation on "Hello World":

It was quite a journey and took much longer to reverse engineer than I expected. First I'll describe the steps I took, and then I'll summarise the interface.

I started by using an oscilloscope to probe the 5x wires interfacing the CC1110 to the LCD interface. The signal waveforms gave some clues, but not the complete picture. For instance it was pretty clear from the photo below that the upper trace with the 8 regular pulses was the SPI clock (P0_5, SCK) , and that the lower trace was the data from Master to Slave (P0_3, MOSI - Master Out Slave In):

This waveform also told me that the clock SPI clock speed was 2.5MHz, and that the data changes on the trailing edge of the clock (it's difficult to see the faint transitions in the photo above). So the LCD must be reading the data on the leading edge of the clock.

I pondered how I could spy on the SPI traffic, and concluded that the simplest way to deal with the high speed and the 2.5v signal levels would be to use a second im-me! I used fine wire-wrap wire to connect the SCK and MOSI signals from a fully-functioning im-me to my spy im-me, and wrote a simple program to capture the traffic. The spy program was simple - it would read the data into a memory buffer, and stop when it was full. I'd then use the debug interface to read the results out of the buffer. To write the spy program I used for guidance TI's Design Note DN113 and the code in CC1110, CC2510 Basic Software Examples. Although the program started capturing SPI output, the results were inconsistent each time I ran it; data was being dropped. It turns out that on reset the CPU runs on an internal RC clock which is half the speed of the Xtal Oscillator; I added some code to the spy program to select the higher speed clock source and it started giving consistent results.

By interacting with the fully-functioning im-me I was able to get a wide variety of spy traffic and to piece together a lot of how it worked. For instance there seemed to be commands to direct the on-screen cursor, and the graphics was being written 8 vertical bits at a time per byte transferred. It was also clear from the addressing that the data was being sent MSB first (the spy program was reading it LSB first).

But there was a problem - I couldn't understand how the LCD could distinguish between the command bytes and the data bytes. I would have expected either escape characters to enter/exit data mode, or byte-lengths for the data, but there were none.

I resorted to the internet, and searched for SPI LCD interface specifications for clues. After many blind alleys I found that Sitronix's range of SPI-based LCD Driver ICs. The ST7565S was particularly interesting because (a) it supports a similar size LCD to the im-me, (b) it has an on-board PSU requiring capacitors wired exactly like the capacitors surrounding the LCD connector on the im-me, (c) many of the commands I had decoded from the SPI spy were identical.

The ST7565S data sheet also gave me the final clue I needed - an additional wire to the driver IC (A0) indicates whether the byte is a command or data - solving the problem I was struggling with earlier. With a quick modification to the spy program I was able to confirm that P0_2 is the output from the CC1110 to the LCD driver's A0 input.

So the connections (from the top of the connector to the bottom) are, using ST7565S terminology:

P1_1 - /RESET (I think) -- Pulse low at power up, keep high all the time otherwise

P0_2 - A0 -- Low for a command byte, high for a data byte

P0_5 - SCL -- SPI clock (SCK in SPI terminology)

P0_3 - SI -- Serial Data (MOSI in SPI terminology)

(Note, my guesses for these signals in my original post were wrong).

Now that I had confirmed what the signals and commands were, it was easy to write a small test program for the im-me that would bring the LCD to life. The test program verifies all basic operation. It also exercises commands documented in the ST7565 data sheet that the im-me doesn't use (Display reversed, and Display start line set). It doesn't yet demonstrate contrast adjust (Electronic Volume Mode Set), and I haven't tested Power Save mode either.

The only thing remaining unexplained is a couple of commands in the initialisation sequence that don't appear in the ST7565 data sheet.

Here's the test program's source code I developed using the sdcc compiler.

Fantastic work! A completely fresh and original hack, I love it. On the protocol driver implementation side I've been trying to collect all the reverse engineered drivers into a sourceforge project im-megpldrivers (page, c driver, and svn up so far). If you're interested in posting anything up, I think it'd be fantastically helpful to other hackers. Either way, love the blog, keep up the good work!