Graphical 3.6" 128x64 Display Optimizations

I received it today and I connected it with jumper wires to FEZ Panda.

I tested the performance of the Flush() method and got ~20ms per call.
I tried different things to optimize it and the best improvement was obtained replacing Locate() with this code :

private static readonly byte[] locate = new byte[3];
public static void Locate(int x, int y)
{
    _DC.Write(false);
    locate[0] = (byte)(0xb0 | y);
    locate[1] = (byte)(0x10 | (x >> 4));
    locate[2] = (byte)(x & 0x0f);
    _spi.Write(locate);
}

Now a Flush() call takes a little more than 12ms.

I don’t think it can be improved much more without doing partial flushes

That is almost double the speed. I also have added a third large font but didn’t update the code online. Waiting for the code share website :wink:

I had tried your new method on my application. (My Console app that went to the Makers Faire).

And It’s amazingly faster than before, and can be noticed with the bear eyes!
I can cleary see the different between the previous method and your method.

Godd job. :clap: :clap:

Thanks for sharing!!

Remember Sam, I told there are many thing you can do to make it faster. His optimization is on full screen refresh but you can do partial screen refresh I think.

:clap:

I will look into that!

Now, quiet busy with many things that happening lately! ;D

[quote]And It’s amazingly faster than before, and can be noticed with the bear eyes!
[/quote]

Heh, heh…Panda…‘bear eyes’… :wink:

(I know warped sense of humor…)

I just tried this change by calling ‘flush’ 100 times in a tight loop with the same byte array.

Standard driver: 27.886 seconds or 0.027886 seconds/flush
New locate: 1.922 seconds or 0.001922 seconds / flush

That is a whole lot faster, but the huge speed up makes sense when you consider that each call to SendCommand has a 10ms thread sleep in it.

            static private void SendCommand(byte c)
            {
                _DC.Write(false);
                Thread.Sleep(10);
                sb[0] = c;
                _spi.Write(sb);
            }

Just for fun I tested both the array copy and locate by themselves by commenting out everything else in ‘Flush’ and came up with the following times. (Same method by calling 100 times in a loop).

Array copy: 0.0799 seconds
Locate: 0.5201 seconds

I was surprised that the bulk of the time is still spent in Locate.

Instead of calculating the values with Locate each time (since they are the same each time you do a flush) I modified flush like this:

           static public void Flush(byte[] vram)
            {
                locate[0] = 176; locate[1] = 16; locate[2] = 0;
                for (int i = 0; i < 8; i++)
                {
                    _DC.Write(false);
                    locate[0] += (byte)i;
                    _spi.Write(locate);
                    //Locate(0, i);
                    //Array.Copy(vram, i * 128, one_line, 0, 128);
                    //_DC.Write(true);
                   // _spi.Write(one_line);
                }
            }

I obtained the values for the ‘locate[]’ array by dumping out what the location function was generating. This took the ‘locate’ portion of the flush time down to 0.4872 seconds for 100 flushes. Not really a big improvement. So perhaps the SPI write to set the location is taking a lot of time? Commenting that line out showed that 100 cycles now takes 0.1263 seconds.

Anyhow, I thought this was an interesting topic and I’m glad it got started.

A few other things to play with: this little display is really pretty fast and has internal buffers so you can really feed data to it fast. I changed the SPI configuration to what is shown below and not see a 100 cycle flush time of 0.8773 seconds! After about 5 minutes of running the display did goof up so I’m guessing that the SPI clock is too fast (just trying to see how fast it would go :wink: The SPI clock does not have as big an effect as lowering the chip select setup and hold times. I just set the SPI clock back down to 10,000kHz and it seems pretty stable (but this is still a wee bit optimistic I think.)

SPI.Configuration spiconfig = new SPI.Configuration((Cpu.Pin)SelectPin, true, 1, 1, false, true, 25000, SPIModule);

).

Nice, using your SPI.Configuration I get 6.6ms/flush instead of 12.6ms

How are you measuring your flush time?

                t = DateTime.Now.Ticks;
                FEZ_Extensions.Large128x64Display.Flush(this.paint.vram);
                d3 = ((float)(DateTime.Now.Ticks - t)) / TimeSpan.TicksPerMillisecond;