A picture is worth 2 re-writes

A project log for PIP Arduino Web Browser

Surf the web using an Arduino and an ethernet shield. Because you can.

GilchristGilchrist 05/13/2015 at 04:250 Comments

From early April 2014

It's about time for a diversion into visuals. Output via the serial connection isn't where I wanted to end up so I needed to look at an LCD display.

I already had a 1.8" 160x128 TFT LCD SPI driven screen knocking around and had even written a custom library to drive it.


The Adafruit GFX and UTFT libraries both worked with the display but there were problems.

The UTFT library was extremely slow, as it seemed to ignore hardware assisted SPI, and bit banged away in software. It also didn't over-ride the print procedure and had it's own methods of text output. Shudder.

The GFX library was comprehensive and used the standard print procedure but also chewed through the KBs.

I took the Adafruit GFX library as a start and ripped out everything not related to the display I had. I also improved the speed of some of the routines, like circle drawing. Optimising the calculated sectors gained a 4 times speed improvement.

This library is available on Github [1].

Character drawing was still extremely slow and the reason for this is that each character is draw pixel by single pixel. For each pixel drawn, the following data needs to be sent through SPI:

1 bytewrite command column set
4 bytesstart and end column position for pixel
1 bytewrite command row set
4 bytesstart and end row position for pixel
2 byteswrite data to ram command
2 byteshi and lo pixel colour byte

Add those up and each pixel write requires 14 bytes to be written down the SPI bus (and a whole load of Arduino pin updates). This means a compact 6 x 8 pixel font is going to require 6 x 8 x 14 = 672 bytes written. Phew!

Now do that about 26 x 16 [2] times for a full screen of text and that over 279 KB to be written.

The only advantage the GFX library has in drawing characters pixel by pixel is that text can be rendered on top of existing pixels or background colours and these will show through the 'blank' undrawn areas.

As I didn't really care about that [3] and was really just interested in block text output, I re-wrote the character output to define the drawing window once, and draw the 6 x 8 character pixels in a stream.

There was still the initial 12 byte setup but in total just 12 + 6 x 8 x 2 = 108 bytes per character drawn. Or just over 44 KB per page. That was over 6 times faster. Sweet.

I encoded the 6 x 8 pixel font in the usual LCD library way, as vertically oriented bytes and the 6th bit/column always a 0x00 so that was omitted. Because: space saving.

// Standard ASCII 5x7 font for chars 32+

static const char font[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, // Space
0x00, 0x00, 0x5F, 0x00, 0x00, // !
0x00, 0x07, 0x00, 0x07, 0x00, // "


The LCD display was 3.3v, and I'd hooked it up with 6.8K in-line resistors to drop the Arduino's 5v down. Hacky, yes, but it seemed to work fine and didn't effect SPI speed at all.

Trying this all out, I then came to the obvious conclusion that displaying a webpage in 26 x 16 characters at a time isn't going to be pleasant at all. Even my old Commodore 64 had a better resolution. [4]

So I had to do choose another LCD display (a whopping 320 x 240 pixels this time) and write another optimised-for-text library again. [5] You're welcome.

This library didn't do anything except draw rectangles or characters. I figured I could do without diagonal lines and things to save space. And 53 x 30 characters per page would have to do.

Next up: back to parsing HTML.

[1] The LCD is this one from Banggood!W

[2] 160 / 6 = 26, 128 / 8 = 16 of course.

[3] In fact, overwriting all pixels underneath a character is an advantage for text-based output. You don't have spend time erasing the previous character contents first.

[4] Only just. It had 320 x 200 pixel resolution. Or 40 x 25 characters (at 8 x 8 pixels each).

[5] That LCD is also from Banggood!W