HD44780 LCD Signal Piggyback/Sniffing/Reverse Engineering

Hey,

I've thought of this solution for a number of projects -- currently I'd like to read a 2x16 LCD, I'm hoping it's going to be an HD44780 so I'm working with that. Basically it's a device I want to read the output from and this seems like the easiest way. I can think of three approaches (aside from a camera and character recognition),

  • I've read that the HD44780 can be set to dump it's current display to an output, would it be feasible to use this without having control of the device sending it commands?
  • Piggyback the lines controlling the LCD and decode the commands live without interrupting the signal
  • Intercept the interface completely using an Arduino to emulate the display and decode the commands (with the option of re-displaying the same output using the Arduino)

Has anyone done something similar or have any advice to offer? Between figuring this out and interfacing with some buttons one could make a huge number of devices remote operable.

Phil

substatica:
Hey,

I've thought of this solution for a number of projects -- currently I'd like to read a 2x16 LCD, I'm hoping it's going to be an HD44780 so I'm working with that. Basically it's a device I want to read the output from and this seems like the easiest way. I can think of three approaches (aside from a camera and character recognition),

  • I've read that the HD44780 can be set to dump it's current display to an output, would it be feasible to use this without having control of the device sending it commands?

You can read the contents of the display ram but that requires controlling the interface pins.
The problem is even if you isolate the interface pins from whatever is controlling it while you read it,
you may interfere with other LCD updates while you read the display data.
It may be trying to update the LCD while you are reading the display ram.
It might not work depending on how the display is used.
For example, the display can be scrolled back and forth in display memory or
can have a visible cursor. These are things you cannot determine from just
reading the display ram.

  • Piggyback the lines controlling the LCD and decode the commands live without interrupting the signal

Are you looking at doing this all in hardware or involving a micro controller?
I'm assuming using a micro controller.

This could be done but depending on what is driving the LCD and how fast, it might be difficult
to keep up. While most things driving an LCD don't run at maximum rate, it is possible the LCD
is being driven with data/commands every 500ns, and that would be impossible to keep up
with using an Arduino especially if you are using the slow core routines like digitalRead()
In reality the micro controller driving the LCD is probably not driving it anywhere near
that fast but the update speed of the LCD will be very device dependent.

  • Intercept the interface completely using an Arduino to emulate the display and decode the commands (with the option of re-displaying the same output using the Arduino)

Kind of the same issue here as above. The one benefit of driving the interface is that you could
control the BUSY signal which could be used to slow things down, however many implementations don't look
at BUSY and assume that things can complete in a certain amount of time.
So this is really the same as the one above.

Has anyone done something similar or have any advice to offer? Between figuring this out and interfacing with some buttons one could make a huge number of devices remote operable.

While I haven't done this, I had a long exchange with CrossRoads a while back
about trying to do this very same thing for a coffee machine that used a glcd.
It is a similar problem but a glcd is much more difficult because of the additional data involved.

With these types of lcd interfaces, in order to sample/sniff the data, you only need to
sample the data and control lines right when the E signal drops.
If it is a hd44780 interface and it is in 4 bit mode, the problem gets a little bit easier as all the data
you need for a given "sniff" will fit into a single 8 bit byte.

Depending on what the goal/need is there are a few options, but I don't believe
it will be possible to do using only wires hooked up to an Arduino,
there will need to be some external hardware involved.
In the simplest case, you will need some sort of latch to capture the data and control lines
when E drops, then you have to do something with that data sample.
What you do depends on what you want/need and if a processor like an arduino is involved
and how you want to move or buffer the data samples.

The solution that CrossRoads was looking at involved using a parallel to serial latch.
The data/control lines were latched when E dropped,
An interrupt was sent to the AVR, then SPI was used to shift the bits out of the latch
into the Arduino where the data could be buffered and then processed.
On a ks0108 glcd interface, a 16Mhz AVR was simply not fast enough to keep up
with the glcd updates.

With a hd44780, especially in 8 bit mode, I think this type of approach
would probably work since most real devices are not driving the hd44780
anywhere near its maximum.

Hope that gives you some ideas.

--- bill

I was hoping to just use an Arduino with some hook-up wires, I'll have to do more research into latching if I'm to attempt that. Thanks for the insight.

You might be able to get away with only wires hooked up to the
hd44780 data/control lines if:

  • the device is not driving the interface more than say a once every few (10+) micro seconds.
  • The hd44780 is being used in 4 bit mode,
  • you use direct port i/o to read the 4 bits, RW, RS all in one 8 bit read/sniff.
  • you use the E signal as an interrupt line to trigger your sampling.

Things like digitalRead() are a total pig and take several microseconds.
You simply can't afford that amount of time to examine each LCD pin.
The key will be to avoid as much arduino core code as possible to get
the performance up. i.e. don't call things like digitalRead() and use
direct port i/o to read all 8 bits of the AVR port at once.
When reading multiple pins like this, direct port i/o will be
100s of times faster than using digitalRead() for each pin separately.

Even with direct port i/o,
The concern I'd have is for the timing between the two nibbles of the 8 bit data/command.
There is no delay required there. So depending on how fast the device updates
the 2nd nibble and how fast your code can respond to the E signal interrupt and
get the data sampled, you might miss a sample.
And if you miss a sample, you can get hopelessly out of sync.

But it might work just fine if the micro controller running the LCD isn't that fast,
which might be the case.

A quick look with a logic analyzer would answer the question.
You would need to look at the E line to see how often it is being strobed.

--- bill

update:
If using E to create an interrupt there is also the concern about other interrupts
delaying the processing of the E interrupt.
Depending on the needed timing, the normal millis() clock interrupt might block the E interrupt for too long.
So in some cases, you might have to disable the system timer.

Sigh The device arrived, a keypad with an LCD display. This is what the LCD controller board looks like,

The info on the board looks to be,

RoHS TM162B9DCWU6 P-4 2006 05

On the bottom of the LCD casing it reads,

201001201409 08/10 TM16B9DCWU6(0-7) 7000051

Can anyone shed some light on this? 18 pins on the test interface, 24 leads on the bottom which connect to the main board and 8 on the side which aren't used. Seems now like this is a custom LCD. Any ideas as to where to start? It would be tedious, but would intercepting the ribbon and mapping out the LCD segments be the simplest (though easy to wreck the LCD that way too)?

The ribbon has ~96 leads and the LCD matrix itself looks to be 20 (pixels?) high by 80 wide. Any ideas what the test array might yield or the 8 point connection on the other side?