reading LCD data

Hi gang,

Is there any reason I couldn't connect the data lines, R/W, D/I and CS1 & CS2 lines to 2 parallel in/serial out shift register, use the falling edge of the Enable signal (inverted) to clock the data in, and trigger an interrupt at the same time to read the 2 bytes in via SPI.transfer's and then spit them out the serial port/USB to a PC?


If I understand correctly what you wanting to do, I think it might be tricky.

Normally for ks0108 type displays like this, the data on the data bus
is only valid while enable is high.
Take a look at the timing on page 11 of the data sheet.
tdhr and tdhw are very short. 10 and 20ns respectively.

So if you try to grab the read data as E drops, the data won't be guaranteed to
be stable very long (10ns) as the display turns off its drivers.
Normally you grab the read data before E drops.
But it might still work as the data lines should all be stable when E drops.

On writes, you have a similar issue but the one that stops driving the bus
is not the display.

Now if you could delay E going to the display but use the real
E to drive your chip, I'd think you could for sure make it work as you
could delay the E to the chip essentially indefinitely even while the SPI transfer was going on.

I'm curious what you trying to do.
Snoop on the display?
Or design a two SPI interface?

--- bill

Goal is to snoop on the display.
Looks to me like inverting E to use as clock, use E as is (low) to to create ATmega interrupt and clock data out with SPI should do the trick?

I'm not following.
You can't sample the data when E rises as its not valid yet.
(this is true for both reads and writes)

But I'm thinking in terms of "latching" rather than "clocking" the parallel data
so maybe I'm not understanding what you mean by using E for a clock.

So are you looking to latch the all the data when E falls?
and send the interrupt when E is low?

The one "gotchya" to think about is the BUSY status bit
which is D7.

When you are in read status mode, you don't have to hump E to get D7 (BUSY) updated.
It is "live" while E is high.
Some implementations that monitor BUSY (like the glcd v3 library) poll the BUSY status
while E is high rather than bump it up and down for each busy status check.
So if you use E falling to grab the data, you will only see the value of of the "BUSY" status
when the E is lowered, which will never be set in an implementation that polls busy
with E high.

But that may not matter for you you wanting/needing.

--- bill

What I am thinking is to invert E and use that as the clock into a pair of shift registers. Thus E-not will clock the data in.
Use E without inversion to create a low level interrupt to tell the uC to shift in the 2 data bytes.
I will only care about the data being written to the device. I don't think I care about the device being queried for its busy status, etc. so will ignore that in software.

Goal is to snoop on the display.

Sorry, I didn't understand what you were trying to do when I posted my earlier reply. The main problem I can see is that you don't have much time to clock the bits in to the Arduino, particularly if the display is being operated in 4-bit mode so that 2 nibbles are sent to the LCD in quick succession.

What I am thinking is to invert E and use that as the clock into a pair of shift registers. Thus E-not will clock the data in.
Use E without inversion to create a low level interrupt to tell the uC to shift in the 2 data bytes.
I will only care about the data being written to the device. I don't think I care about the device being queried for its busy status, etc. so will ignore that in software.

Still not sure what you are trying to do.
I'm assuming that you are trying to trying to snoop the communication between
some processor talking to a glcd by looking at the glcd pins.
But I don't understand your terminology of the word "clock" and how you intend to use E.
(some clocks are rising, some are falling etc...)
I see this more as a latch operation.

I'm not sure what value this would be as you can see the actual display and the communication
interface is fully documented.
But maybe for some sort of diagnostic.

In order to snoop the all signal and data lines to the glcd
you can only sample them at specific points in time.
They are not all stable before E is high and they are not all stable
once E is high.

For writes to the glcd, the lines are only all stable tdsw (200ns) before the master drops E.
The master that is writing to the glcd can alter the data lines as much as he wants and as slow
as he wants as long as he waits tdsw before he drops E.
But since you don't know when E is going to drop, you have no idea when tdsw before E occurs.

Reads have a similar issue.
On reads, the data from the glcd is not valid until tddr (320ns) has passed from
when the master raises E.

So you have to use the falling edge of E to sample all the lines but the state of the lines are
guaranteed to be valid very long after E drops. Like 20ns on reads and 10 ns on writes.
That is why I said it might be "tricky".

Reads can be a tricky area. While the spec usually specifies some minimum cycle time
(typically 1us) with 450ns min high/low pulses. You don't have to do that on all reads.
This is because there is a dummy read that must be done in order to clock the internal hardware
to latch the real data. So every other read will be a dummy read and the time between a dummy
read and the real read can intentionally "violate" the spec in order to make them faster.

Even ignoring all that, It may be tough to SPI the data away before the next latch event occurs.
Even at 1us per read/write to the glcd (which is the theoretical min between them)
that means you have to take the interrupt, Arm the SPI hardware to get the data
and pull all 16 bits across which means your SPI clock would have to be higher than 16Mhz
in order to meet the 1us back to back read/write timing that is possible.
Doesn't seem possible using typical AVRs in Arduinos.

--- bill

How are graphic LCDs typically used? Write data, couple of status reads, write data, couple of status reads? I could add a couple more gates and keep the read clocks out, that would allow more cycles to get the data.
Here's what I'm thinking of doing and my vision of how it would work.
[edit - fixed file name]

I don't see anything in the data sheet about a 4-bit mode. Looks like bytes are sent every time.

How are graphic LCDs typically used? Write data, couple of status reads, write data, couple of status reads? I could add a couple more gates and keep the read clocks out, that would allow more cycles to get the data.
Here's what I'm thinking of doing and my vision of how it would work.

This web address was hidden your post. Capture timing.emf
(spaces in file names are not a good thing - as you can see above, it confuses many parsers......)

I can grab the file and download it but I don't know what it is. What kind of file is this?

The interface is always 8 bits as there is no 4 bit mode.

I'm still unclear what you are really trying to do.
I also am still not understanding your terminology for "clocks".
There are no "clocks" in a ks0108 style interface.
The interface can read, write, read status, and write commands.
And E with the control lines synchronizes the operations between
the host and the glcd with it being determined by both edges
of E.

Maybe there is a misunderstanding which way some of the
signals in the ks0108 interface go?

All the control lines including E are inputs to the glcd.

As far as usage goes, it can vary substantially.
It will depend on whether the application has a frame buffer or not
and how smart it is with respect to remembering and keeping
track of where the hardware address registers/counters are.

If there is no frame buffer then there will be an intermixing of reads and writes
as to set a pixel means reading the lcd page to the host, Oring in the pixel, and
writing the page back out.
If the host s/w is not very smart there will be many commands to set row and column
going on in between the reads and writes.

The data/command pattern will also very dramatically depending on what is being done.
Say drawing a line or circle vs drawing a bitmap vs rendering text. They will vary substantially.
In fact even rendering text can vary quite a bit depending on the size of the font and the alignment
of where the font is being rendering on the display.

The glcd v3 library code I've done is very smart, but does not use a frame buffer.
So while it must do reads for the frame buffer data
it will send the absolute minimum read/writes/commands to the glcd to perform the operation.
Depending on the operation, including when rendering text, if the pixels to be rendered on the display
align properly, then no reads will be done and full bytes will be written back to back to back.
All the other libraries I've seen will do many more commands and read/write operations
to get the same thing done.

Some additional details an what you are trying to do would be helpful.
What are you trying to debug?
If you have access to the host, there are much easier ways to track data/command sequencing.
And what you can do will vary depending if you are going to only sniff the glcd pins vs
sit between the host wires and the glcd pins.

--- bill

I fixed the file name Bill. The file type was described as "metafile, scalable", (.emf) it shows up as a nice drawing in the forum for me.
What I want to do is capture the data that is being written to the LCD and pass it in to a PC where it can be displayed remotely. The PC will take care of interpreting the data and making it viewable.

When I refer to clocks, I am trying to use the 2nd falling edge of the Enable line to clock data into a parallel-in/serial out shift register (2 of them to capture the 8 data and 4 other lines).
Pin 12, the edge triggered Storage Clock Input
Then pull the Parallel load pin low to move the data into the output shift register, and read it out via SPI.
Figured E & R/W could be hardware logic manipulted to create the Storage Clock to the shift register and interrupt the ATMega so it could do the SPI.transfers. The SS pin would do the parallel load function, and SCK/MISO would pull the data in.
The display is part of a high tech coffee machine, the display is updated in response to users pushing buttons, so I'm thinking it will not be changing all that much, but I haven't seen it in action myself.

I am not writing the PC software, just passing the data along via USB port (FTDI serial/SB adapter).


I suppose the other thing I could do is parallel capture the data using 20-pin octal register chips (like 74F374), and read it in parallel via two direct port reads. Would that be fast enough?
Using PA and PB on an ATMega1284.
PB is the SPI pins, which I was only using for this, so all of PB is free for the datalines, and I can make 1/2 of PA free for the other lines.
The data would be captured and show up at the port pins after 2nd falling edge of E, which would also create the interrupt to signal data available to be read.
If you can't open the .emf, I'll do screen capture some other way, or draw it in powerpoint & do a save-as into .jpg.

I don't see anything in the data sheet about a 4-bit mode. Looks like bytes are sent every time.

That makes it easier. I've now read the datasheet, and I don't see on the datasheet any indication of how long the host must wait after sending one data byte before sending the next. The implication is that the host must wait on the busy flag. So I think you will need to gate out the read requests as you propose.

I suggest you connect a scope to the E and R/W pins and measure the minimum time interval between one write request and the next, so you can see how long you have to clock the data out of the shift register via SPI.

bperrybap has pointed out that the timing could be tricky, however I suspect that the display is being drive by an mcu and the setup and hold times used will be much longer than the minimum values shown on the datasheet. You can check this with a scope too.

I suppose the other thing I could do is parallel capture the data using 20-pin octal register chips (like 74F374), and read it in parallel via two direct port reads. Would that be fast enough?

That depends on (amongst other things) what other ISRs are active on the MCU, e.g. timer 0 and hardware serial. Your interrupt might occur just after entering one of these ISRs, and unless interrupts are re-enabled inside that ISR, you will have to wait for it to complete before your interrupt gets serviced. It might be better to disable those two interrupts if you can manage without them.

As I said in my previous post, I think you need to scope the E and R/W lines to see how much time you have to read out the data before it gets overwritten.

Ok, I get where you trying to go.
As far as the .emf file format goes, I looked it up, it seems to be some kind
of goofy proprietary Windows print file format.
(No Windows or MAC stuff in my life)
Odd that it is totally invisible to Firefox. I would have figured that the
attached file would at least show up in the attachments area of the post.
It is better to always something standard like jpeg, png, gif, or pdf files.

For what you are doing, you can "probably" totally ignore any and all read operations.
You should only have to need to track writes and commands.
But you will also have to mimick some of the internals of the chip and glcd module
(there are 2 chips on that module) as well because the
address counter that is used to set a column automatically increments after each read or write
The reason that I said "probably" above because it is theoretically possible that some host
code might do something like:
read, read, read, and then a write. If the column was set to 0
the the write would be done at column 3 because the 3 reads advanced the column address.
Normally this is not done as the only time you do a read is just before you do a write to
the same location (otherwise why would you need to read?)
and to write to the same location as the read, you have to reset the column
back to where the read was done because it advanced after the read operation.
And to reset the column is a command.
But all the mimicking can be done on the PC side if it has all the write and command

So I'm betting you can get away with only grabbing the writes and the commands.
but you will have to handle the auto column increment and deal with mimicking
both chips that are on the module (each one controls 64x64 pixels)
and tracking the row and column of each chip separately.
Handling auto increment can also be tricky, some displays wrap back to 0 and some
stop when the highest column is reached.
I have seen some host code that takes advantage of the wrapping back to 0 even though
not all displays work this way.
Best thing to do here is to wrap back to 0, that way you cover the guys that take advantage
of this for a display that supports it and for the guys that don't use it, it won't matter.

By ignoring the reads and read status operations, that will buy you some extra time
to transfer the data.

But my concern is that it looks like an AVR chip at 16Mhz may not be able to keep up.
In order to meet the worst case scenario of back to back writes you need to push
the 16 bits in the shift register across and deal with it in 1us. Just to push the 16 bits
in 1us means a 16mz clock and the AVR SPI looks like the maximum it can run is
F_CPU/2 or 8mhz on standard Arduino boards.
Now in reality there is probably host overhead and there is probably a status check
for BUSY so that the back to back write or command time is at least 2us and probably
in reality it is much longer.
Still it looks like it might be iffy in the worst case
because there is still some AVR processor overhead
to process the SPI registers and deal with interrupts, if it is interrupt driven, and then
you have queue up the data into something that sends the data to the PC.
At 3us between writes, which I could see happening on fast and smart host,
or a host that uses a frame buffer,
that is only 48 cycles on a 16Mhz AVR so it could be less than 48 AVR instructions between back to back glcd writes.

The thing to keep in mind is that it is also possible to ping/pong between the two chips when writing.
If you do this, you can in some cases ignore BUSY (not check it)
as the amount of time to do a write on chip 0 is enough that chip 1 will be ready and vise versa.
This is very effective for slamming out a frame buffer.
You set both chips to column 0 and then ping pong between them to flush out the frame buffer.
In this case, you can get a write operation happening every 1us on a fast host, probably
even on a 16Mhz AVR host.

Any idea the horse power that is driving the glcd?

Lots of unknowns and variables here......

--- bill

Guys, thanks for all the advice on this.

Okay, here's the picture as a .jpg
I didn't think .emf was propriety as the free software from offers the format as an export option, along with .bmp.
It looks really nice too. I did a screen capture, pasted into powerpoint, and saved as a .jpg.

Unfortunately I do not have access to the machine, the fellow I am working with who does is located I don't where and is a mechanical engineer and this stuff just goes over his head. I'll pass along your questions and ask him to see what he can find out.

I have a few comments on your diagram:

  1. I think your comment "Gate also allows a Low during start of Read cycle..." is wrong. What the read-cycle diagram that you copied from the datasheet shows is a read cycle after the end of a write cycle, rather than a read cycle in isolation. So I don't think you will get any false interrupts from read cycles.

  2. The answer to "When does E go back high?" is when the host initiates a new read or write cycle.

  3. If you are using the 74HC597, then I would use the 2-input nand gate, connect the output of the nand gate to STCP and hold PL permanently low, so that the data is transferred directly into the shift register when E goes low at the end of a write cycle. Also use the nand gate output to generate the interrupt.

  4. If timing is more critical, then you could use the input latches as a 1-event buffer something like this:

  • have the output of the nand gate clock a D-type latch as well as the STCP clock of the 74HC597
  • have the output of the D-type latch generate the interrupt and also make it readable through an input pin
  • have an output pin controlling PL and also going to the reset input of the flip flop
  • hold this output pin high normally
  • in the ISR, pulse the PL pin low and high again. This transfers the data to the shift register and also resets the interrupt
  • then shift the data out via SPI
  • in the meantime, another write cycle may take place, causing the new data to be latched in the input register
  • at the end of the ISR, read the state of the D latch to see if another cycle took place. If so, go back to the start of the ISR. If not, exit the ISR.

This allows you to process multiple writes without returning from the ISR each time, and allows another write to occur before you have finished shifting out the data from the first.

I did a screen capture, pasted into powerpoint, and saved as a .jpg.

Wow, long way around to do that.
Get a screen capture tool.
These guys have a great free set of tools for windows:
note: screen capture is also part of the freeware image viewer.
I used the faststone image viewer and built in screen capture
for years before I finally fully abandoned Windows.
It can convert anything to anything including batch modes,
and has some very nice image editing features.

You will need to save all the control lines:
R/W, CS1, CS2, and D/I as well as the 8 data bits.

I just noticed that the timing diagram signal names does not match their pinout signal names (typical for these types of display)
All the control lines R/W, DI, and the chip selects are supposed to be setup before E is raised.
(tAS which is 140ns)
Think of E being high as the output enable signal to the glcd for the data bus.
And the R/W determines whether the data bus is driven or used as input.

Pretty much every ks0108 AVR library I've looked at violates that tAS timing requirement.
In fact some set them simultaneously set some of the control lines with the raising of E, which clearly violates
having them set up prior to raising E. Yet this does seem to work on most glcds.
I chose to honor tAS, so the glcd library does honor tAS.

So you may have to actually look to see what they are really doing vs what
they are supposed to be doing.

I still have concerns about being able to retrieve the data fast enough even over a SPI interface.
Unless you jump to something like a chipkit UNO32 where you have tons more speed.
pic32 also has DMA capabilities which opens up other options than a SPI interface.

After thinking a bit more about the worst case scenario, it is actually a screen clear.
In that case the host is slamming out bytes of 0, to every memory location.
This operation could be highly optimized and easily do back to back writes.

I'll hook an analyzer to my glcd and take a picture of a screen clear operation
so you can at least see a real world example of screen writes when using a 16 mhz
AVR that honors all the proper timing.

I'll post a picture of that later today.

--- bill

Thanks Bill.
Getting screens ready to post goes quick, been doing it that way for quite a while.
Having it as powerpont also lets me add arrows, notes, etc when I want to.
Having to upload outside of the forum is a pain.

Is it possible the display uses a different chip? Datasheet says
"The display control instructions control the internal state of the NT7108. Instruction is received from MPU to NT7108 for the display control."
Is the timing similar to ks0108 timing?

I had planned to capture the 4 lines and the 8 data lines.

Thanks for the follow up.

You can use faststone to quickly add text on top of graphic images.
I liked it because it worked on Windows and avoided having to use a Microsoft based tool.
I found that the Microsoft tools tended to dork with the images and it is quite difficult
to maintain image quality.

That chip, including the timing works the same as the chips used in the “ks0108” modules.
Just about to hook up the analyzer and take a picture.
will post shortly.

— bill