views:

104

answers:

5

I have an embedded project that I am working on, and I am currently coding the character LCD driver.

At the moment, the LCD driver only supports "dumb" writing. For example, let's say line 1 has some text on it, and I make a call to the function that writes to the line. The function will simply seek to the beginning of the line and write the text (plus enough whitespace to erase whatever was last written).

This is well and good, but I get the feeling it is horribly inefficient sometimes, since some lines are simply: "Some-reading: some-Value"

Rather than "brute force" replacing the entire line, I wanted to develop some code that would figure out the best way to update the information on the LCD.

(just as background, it takes 2 bytes to seek to any char position. I can then begin writing the string)

My idea was to first have a loop. This loop would compare the input to the last write, and in doing so, it would cover two things:

A: Collect all the differences between the last write and the input. For every contiguous segment (be it same or different) add two bytes to the byte count. This is referenced in B to determine if we are wasting serial bandwidth.

B: The loop would determine if this is really a smart thing to do. If we end up using more bytes to update the line than to "brute force" the line, then we should just return and let the brute force method take over. We should exit the smart write function as soon as this condition is met to avoid wasting time.

The next part of the function would take all the differences, seek to the required char on the LCD, and write them.

Thus, if we have a string like this already on the LCD: "Current Temp: 80F" and we want to update it to "Current Temp: 79F"

The function will go through and see that it would take less bandwidth to simply seek to the "8" and write "79". The "7" will cover the "8" and the "9" will cover the "0". That way, we don't waste time writing out the entire string.

Does this seem like a practical idea?

+2  A: 

Assuming that the offset into the display auto-increments and it is a single write to output each successive character, I would be inclined to simply write the entire display line every time unless there is a specific performance problem you are trying to fix. ie: Unnecessary optimizations are potential future maintenance headaches and your time "optimizing" would be better spent on something that actually does affect the performance of the overall application.

Note: If the display update IS actually an application affecting performance problem, you probably have a sense of how much faster it needs to be....then you (and not us) can be your own guide to how much optimization is enough.

Tall Jeff
A: 

The implementation you are planning seems to be too complex for the problem. All the comparing needed may actually slow down the operation, if the processor is not fast.

If you only need to update for example the temperature value, you should just update the temperature value and ignore the fixed texts. You need to have the coordinates in memory for each field that needs to be updated. Then just move the write position to that location and write the value. That is how I usually do it.

If the screen update is still too slow, you may consider using Assembly language. For example, a few years ago I made software for a wristwatch type device with dot matrix LCD display. The display update was too slow (nearly a second to update the whole display for example when scrolling), so I wrote just the lowest level routine in Assembly (replacing about 20 lines of C with 30 lines of Assembly). The resulting function was half the size and 3 times faster than the optimized C function, and now the display update speed was adequate.

PauliL
+2  A: 

It doesn't make any sense to optimize this. Transmitting 20 bytes at 9600 baud takes the hardware 21 milliseconds. And takes the software a few microseconds. Fast enough to be able to update the display faster than the human eye could ever perceive by a factor of 2. And it isn't like you need the "bandwidth", there isn't any additional data that I can think of that you'd want to multiplex on the serial channel.

Hans Passant
@Hans, you are assuming that the LCD controller is character based, there is HW serial interface with 20 character buffer, and the display contains only a single line of 20 characters. It is entirely different case if the serial interface is just a MPU pin that needs to be controlled by software, and the LCD is bitmapped and contains multiple lines.
PauliL
@Paul, agreed. But the OP is talking about "writing a string".
Hans Passant
A: 

That way, we don't waste time writing out the entire string.

You shouldn't be wasting much time at all, certainly less than the time it would take to do all this checking.

What is the connection to the LCD? SPI/I2C/parellel?

Whatever it is, if DMA is supported by the SoC on the interface, use it.

If not, you shouldn't be waiting around between tx bytes, especially if the instruction clock of the processor is much higher than the clock of the data link. This is likely true as most character display's i've worked with have low max clock specs.

Use either an interrupt routine to handle sending each byte or use a 'hybrid' approach if you can control interrupt routing (are are doing this for power savings). Theres an interesting write up here

Mark
The connection the LCD is a 9600 baud serial line.
chris12892
A: 

For a character display, this kind of update optimization is what the curses library was all about. Back in the day, when we talked to large computers with dumb terminals and phone lines at 1200 baud or less, it was often difficult to update the screen fast enough to make programs feel interactive over the slow modem link. The curses library made it practical by keeping a cache of what should be on the user's screen and sending a close to optimal number of move and erase commands interspersed with normal characters for display. It did require that the terminal support some form of cursor positioning.

The curses library lives on in a couple of forms, and ncurses, for instance, is well known, open source, and licensed under the GPL.

In principle, you could adapt ncurses to talk to your display controller and let it do all the hard work.

The open question is whether it is worth the effort. At 9600 baud, you can send 960 characters per second. That is fast enough to completely repaint a 4 line by 20 column LCD 12 times per second. So unless you are running in a PIC or ATtiny where you might have to implement that UART in software and need the cycles to actually do something useful, there is likely to be little advantage to being too clever.

That said, it still usually makes sense to paint your fixed text once, and just update the displayed values as they change.

RBerteig