Introduction: Arduino - TFT Display of Bitmap Images From an SD Card

Picture of Arduino - TFT Display of Bitmap Images From an SD Card

Following on from my other Instructables on the Arduino and TFT display here is an updated library and Sketch to draw bitmaps (BMP or Raw) stored on an SD Card onto the TFT display.

Most of the available TFT displays have a SD Card slot on the back, the connections to this are usually separate to the display interface so must be wired up.

This instructable will tell you how to wire an Arduino UNO to a 2.2" TFT 320x240 display that incorporates the ILI9341 driver chip. These displays are available at low cost on eBay.

The library and function should work OK with other displays that use that driver chip.

By using an optimized version of the Adafruit_GFX library and an efficient function a raw 320x240 full colour bitmap can be plotted to the screen in 660ms, not bad for a humble UNO.

Step 1: Connecting It Up

Picture of Connecting It Up

Connections are different to those in my other Instructables (this is for my convenience!) you can change the pin allocations, but do use the hardware SPI pins:

  • UNO +5V to display pin 1 (VCC)
  • UNO +5V through a 56 Ohm resistor to display pin 8 (LED)
  • UNO 0V (GND) to display pin 2 (GND)
  • UNO digital pin 7 through a 1K2 resistor to display pin 4 (RESET), add a 1K8 resistor from display pin 4 to GND
  • UNO digital pin 8 through a 1K2 resistor to SD card SD_CS, add a 1K8 resistor from SD_CS to GND
  • UNO digital pin 9 through a 1K2 resistor to display pin 5(DC/RS), add a 1K8 resistor from display pin 5 to GND
  • UNO digital pin 10 through a 1K2 resistor to display pin 3 (CS), add a 1K8 resistor from display pin 3 to GND
  • UNO digital pin 11 through a 1K2 resistor to both display pin 6 (MOSI) and SD card pin SD_MOSI, add a 1K8 resistor from display pin 6 to GND
  • UNO digital pin 12 direct to SD card SD_MISO (or via 1K2, see below)
  • UNO digital pin 13 through a 1K2 resistor to both display pin 7 and SD card pin SD_SCK, add a 1K8 resistor from display pin 7 to GND

Other pin outs at the Arduino can be used by adapting the sketch should you have a display from another supplier or wish to use an existing setup.

You may wish to put an inline 1K2 (or there about) resistor in series with the MISO signal line (between UNO pin 12 and SD_MISO) this will help protect the SD Card in case you accidentally switch the UNO pin 12 to output a +5V logic 1... The SD card might survive such abuse but you may not be lucky... and the resistor will limit the current into the device to a couple of mA.

Bear in mind the display I have incorporates 10K pullups to the +3.3V supply on the SD Card SPI lines, this means that using higher value resistors in the voltage divider (these drop the UNO 5V levels to around 3V logic) will not achieve a reliable logic zero and it won't work! Ideally we would use a logic level converter but resistors are so cheap and they work fine at these frequencies because the stray capacitance of the lines we are driving is not that significant. The display is quite greedy on power so the dissipation in the resistors is not that significant in comparison.

Do not insert and remove the SD card when the Arduino is powered, this can (does!) corrupt the card and it will need reformatting!

Step 2: Libraries and Example Sketches (updated 2/4/15)

You will need the libraries in the attached zip file and the SdFat library (included for convenience). The standard SD library can be used but this requires minor changes to the sketch and will run slower.

The main changes to the ILI9341 library are to enhance speed and to add the pushColors() function, one to handle integer arrays (for BMP drawing) and one for byte arrays (raw images).

In the zip file you will find a folder containing images, put these on a FAT formatted SD card for the Arduino to read (not in a directory!). You can modify the SD library examples to use the above pins to check a sketch can access the files and the wiring is good. If in trouble post a plea for help... I may have made a mistake or may be able to help you get your setup going, bear in mind that it is difficult to debug major problems by exchanging a few messages...

Most of the image files are in BMP format, so it is left as an exercise to convert them to raw format, amend the sketch and see the improved drawing speed.

The example "ILI9341_draw_bitmap" (in the Adafruit_ILI9341_AS folder) sketch uses 90% of UNO FLASH and 54% of RAM for dynamic storage when compiled under IDE 1.6.1.

Only enable Font 2 (or other small font file) or the UNO will run out of FLASH memory!

I use the compiler -O2 option as in my Instructable here. The standard -Os option will make smaller code images but it runs slower (when IDE 1.6.1 used). IDE 1.0.6 compiled sketches may not fit in an UNO as the old version of the GCC compiler produces fast but quite large executables.

In the copies of the libraries in the zip files F_AS_T is disabled and only Font 2 is enabled, be aware of this if you try other sketch examples!

The image drawing function is part of the sketch not the library, this is deliberate as it is all too easy to create a heavyweight memory hungry feature rich library that puts a strain on the AVR based Arduino's capability! Well that's my excuse ;-) Some folk solve this by making a simple wrapper library that contains these functions and calls lower level libraries, so this is an option for the future. You can cut the drawBMP() function out and just use drawRAW() to save some space.

The main draw function prototypes are:

void drawBMP(char *filename, int16_t x, int16_t y, boolean flip)

The file name must be in the 8.3 format, see the SD library documentation. x andy are the coords where the top left pixel of the image will be drawn. See the last Step of this Instructable for the function of the flip flag. The width and height of the image are extracted from the BMP file.

The equivalent one for raw bitmaps is:

void drawRAW(char *filename, int16_t x, int16_t y, int16_t rawWidth, int16_t rawHeight)

As there is just pixel data in this file the width and height of the image must be provided to the function.

The library and sketch is targetted at AVR processors (UNO, Mega etc). I do not have a DUE, so do not plan at the moment to make it compatible with ARM processors. If someone does get the sketch running on a DUE I would be interested to here how it performs, if the SPI can be run at 48MHz then an entire screen update could probably be performed in less than 100ms... To run the SPI at this frequency you would probably need a digital logic level converters.

Note: On 2/4/15 the library sketch has been updated to further improve performance.

3/4/15: Minor bug fix

Step 3: Adding Images

Picture of Adding Images

If you add your own images make sure they are 24 bit color BMP files and they have a width and height compatible with the display. In Windows the free Paint software can be used to crop, resize, flip and save images in 24bit BMP format. There is little error checking in the code, so images can be corrupted by drawing off the screen edge and may not get drawn at all if the file cannot be found or format is wrong etc, but the Arduino should keep going and I have not had a crash yet. I have removed all debugging print statements to reduce the code size, but Serial is called up in setup().

Paint can also be used to pick colours off images to see the 24 bit RGB value, these can be converted using a calculator or a library function to the 16 bit 565 format used for the display.

Raw image files are quicker to draw and can be created straight from the BMP file using a utility called "ImageConverter565.exe", this comes with the UTFT library and is in the tools folder of the library. Use the ".raw" option, load a file and save it. The file will be ~2/3 the size. The pixel ordering means they draw top down too, this image converter is a great little utility that saves me writing a sketch for the UNO to seek BMP files and convert them (I might do that anyway!).

Yes, I had to include a picture of a cat, at least it's a "proper" one ;-) and a mouse.

Step 4: BMP File Format and Graphics Overlay

Picture of BMP File Format and Graphics Overlay

The common BMP format is to store the image in raster fashion from the bottom upwards but the graphics and plot windowing expects an image to be drawn top down. Manipulating file pointers to draw top to bottom slows down image rendering significantly, so the drawing routine and library uses the hardware TFT SGRAM rotation feature, this means we can quickly draw from bottom to top. After plotting the image the display is returned to the normal top left is 0,0 orientation.

If you visually prefer to draw top down then flip the image top to bottom before putting it on the SD card and use the "Top-Down" TD_BMP flag in the function instead of the Bottom-Up BU_BMP flag. This has been done in sympathy with the capabilities of the UNO by sacrificing a neater (but bigger and slower) software implementation and style for a significant performance advantage! The price to pay is a couple of mouse clicks when preparing the image (just flip vertically before saving in Paint).

The displayed images are nice and crisp with vibrant colours, so the screen shots made with my webcam don't do it full justice. The raw bitmap images are more representative of what you will see on the display.

Standard GFX functions (line drawing, text, etc.) can be used and overlaid on the drawn images. As a trivial example the Terminator eyes are made to glow more brightly red in the ILI9341_tftbmp demo sketch by plotting bright red circles in the appropriate place. Again Paint can be used to help work out the coordinates when plotting over images.

Step 5: Raw Bitmap Drawing

Picture of Raw Bitmap Drawing

It is surprising how quickly the humble UNO can plot SD Card images to the screen when the code loops are kept short and sweet. The speed is quite good when using 16 bit raw images in a TFT friendly format because this avoids the tedious conversion of 24 bits into 16 bit words and only 2/3rds of the number of bytes needs to be read. In fact this library and sketch can fetch an image from the SD Card and draw it on screen in less time than some graphics libraries take to just clear the screen...

The library and sketch has been test on the new 1.6.2 IDE. (which I have only just noticed has been released!)

On FLASH size we are pushing the boundaries for an UNO and only IDE 1.6.x will create a small enough file with a single Font 2 (or smaller) loaded. I use optimisation level -02 as in my Instructable here. for speed but the standard -Os helps a tad with smaller size at the expense of a 35% speed reduction.

These libraries are highly optimised version of libraries created by others hence the Adafruit label. All graphics drawing functions are still their under the bonnet ("hood" for readers in the USA). The line drawing algorithm has been optimised and runs much faster than the basic Bressenham method because it uses the fact that short multi-pixel horizontal and vertical line segments can be drawn much more quickly that individual pixels. The further the angle away from 45 degrees (no multipixel line segments) the faster a line will draw. An example modified UTFT graphics test sketch is included to show the impressive speed improvement :-)

Thank you for reading my Instructables, it has been gratifying to get such positive feedback. The message reporting service on Instructables seems to be a little unreliable for some reason, so sometimes I do not see new posts, bear this in mind!

TTFN

Step 6: Library Evolutions and Speed Enhancements

Picture of Library Evolutions and Speed Enhancements

The Adafruit_xxx_AS libraries associated with this Instructable have been enhanced significantly by myself from the originals produced by Adafruit. It could (unintentionally) be the case that the libraries are no longer compatible with Adafruit products, so bear this in mind and do NOT contact Adafruit if you have a problem!

As the changes made are now quite significant it is the intent to rename this library in future whilst keeping the acknowledgement to Adafruit within. If this change does happen then I will create an associated Instructable.

The table shows how significant the performance improvements are, these improvements are a result of adapting the software to the capabilities of the processor and displays. There are no plans to migrate the Library to ARM processors (DUE etc) as I do not have the need, the projects I have planned only need to update the display infrequently (every few seconds) as the parameters being monitored do not change quickly and by writing the software efficiently to only update the areas of the screen that change means I can get flicker free updates.

The result for the 5.2 x improvement reported for line drawing and 6.2 x for triangle outlines is due to enhancements to the Bresenham line drawing algorithm. Essentially making use of the fact that short horizontal and vertical line segments are in the lines (apart from one case at 45 degrees), these segments can be drawn much more quickly than plotting individual pixels.

The 2x improvements are simply made by making the SPI send loops tighter and more efficient.

Step 7: The Future...

F_AS_T

I have tested the F_AS_T option which uses direct port access on an UNO and this is now working fine. Uncomment the line:

#define F_AS_T

in the "Adafruit_ILI9341_FAST.h" file when using Atmega328 (UNO/Micro Pro/Nano) processors. Put // comment in front to disable for other processors.

Run Length Encoding
One of my next graphics projects will use icons, these are simple images such as thermometers, compass dials etc that generally use few colours with relatively large areas of the same colour, this makes them suitable for compression with a Run Length Encoding (RLE) algorithm. RLE is quite simple and fast to compress/decompress so is great for the AVR. This will make pulling them off the SD card and plotting them even faster as the typically the RLE compressed files will be significantly smaller than a raw bit map. Potentially icons could also be stored in FLASH as well. As an example a raw image of 60 x 60 pixel icon is 7200 bytes, RLE of a simple graphic of a warning triangle could be only 1000 bytes.

RLE of fonts

The GFX library contains fonts and the larger ones lend themselves to RLE, this will mean that a UNO will be able to have more fonts resident in FLASH. Watch this space " " !

Comments

atrum88 (author)2017-04-15

hey there love the detail you go for in these instructable mate your Arduino TFT Display and Font Library works a treat just wondering if you have support for the ST7735R for this cant seem to get the SD working on my little 1.8"

cheers

kai

hyohan43 made it! (author)2017-02-26

It didn't work when I used FAT16 SD cards. I got it working with the use of FAT32 memory cards. ?

Bodmer (author)hyohan432017-02-27

OK, great to hear about your success, thanks for the tip about FAT32 cards working.

Hope your project goes well.

Thanks.

jeff1608 (author)2016-07-27

Great tutorial, thank you.

jeff1608 (author)2016-07-27

Great tutorial, thank you.

GerardoM1 (author)2016-03-17

Hello, I bought this TFT:

http://www.ebay.it/itm/Schermo-TFT-LCD-320-x-480-3-2-pollici-Arduino-963573-/121868650556?hash=item1c5ff0083c:g:LbkAAOSw5dNWnLH6

I would mount it on an Arduino Mega and recall the images uploaded to SD with a button ... can you help me?

Thank you and congratulations for the job!

regards,

Gerry

Bodmer (author)GerardoM12016-04-09

Hi, that is a 16 bit interface display. You could try my library here:

https://github.com/Bodmer/TFT_HX8357

HarryDutch (author)2016-01-30

Hi,

Thanks for
this great library! It's really very useful.

Instead of the
"Adafruit_ILI9341_AS" library I tried to use your `TFT_ILI9341"
library from your GitHub because it's a lot faster and leaves more space for my
sketches. It's kind of working to my surprise, but only the colours and the
screen alignment are not correct. I don't know if you’re planning to replace
the Adafruit library by your TFT_ILI9341 for this instructable but if you do I
would be very happy. Anyway, thanks again for your great work!!

RobertoV1 (author)2015-11-11

SD was not working with sd full speed. Only sd half speed worked.

Bodmer (author)RobertoV12015-11-11

Do you use a resistor divider logic level shifter, if so what value resistors do you use?

RobertoV1 (author)Bodmer2015-11-11

Thanks for the reply! I used the schematic and pin described in this instructables, 1.2k and 1.8k

Bodmer (author)RobertoV12015-12-11

OK, some SD Cards like fast transitions between logic levels. Try 470 Ohms and 1K instead of 1K2 and 1K8. Check your display does not already have 1K in line resistors connected to the SD Card, or post a picture of the back of the display board so I can have a look for you.

intriq8 (author)2015-05-11

/me continues to enthusiastically "watch this space" for RLE font developments... ;)

Bodmer (author)intriq82015-05-26

Good news! I have tried various encoding methods and found that the basic run length encoding is a good compromise between reducing the font files and making the rendering of fonts to screen faster. At the moment I have the adapted graphics libraries running with a 480 x 320 display with the HX8357 driver. I can adapt other driver libraries, if you wish to try the new encoded font files then let me know which TFT driver chip you are using, then I can create a demo for you to try out.

TTFN

intriq8 (author)Bodmer2015-06-01

Great, excited to hear it.
So, as you found, a sweet spot with the TFTs in terms of price is those ili9341 2.2 - 2.8inch TFT modules. the 2.4 and 2.6 in particular balance price and size well. They are available with touch screen chip for around $7 delivered. The touch chips work with uTouch library apparently, i started on the touchless ones, though my touch version have arrived now.

I recently saw those 480x320 ones at $12 though, very nice, almost bought it. I take is you're using a mega/stm32 for those right? 16bit interface right? I should try one of those, look like great value. though see this one:

In cheap 480x320, if you didn't see it , you might want to check out the HX8352-A one, http://www.ebay.com.au/itm/190871667912 as it has a touch screen, $1 or so more.

Another interesting one: a 3.6" 400x240 ili9327 for under $10: (with touch apparently) http://www.ebay.com.au/itm/141648004699. (8 bit interface). I ordered one.

I shifted my TFT project to the $5 maple mini using the STM32duino core, feeling limited with lack of space and ram on the favourite 328p... I like smooth big fonts.

I spent quite a bit of time making a universal TFT controller [328p] with your library, i wrote a nice scrolling graphing function, your ringmeters modified/ more parameterised, optimised serial control, with setup of pages/elements/labels, data updates, etc.. all prompted by the need for more space for graphics code and fonts, and the wish to have this work be universal and re-usable in various projects. In this case even moving to a dedicated 328p was not enough, I found I wanted to buffer a lot of stuff in ram for the data logging and graph, and sd bitmaps were out of the question, and drawing could always be faster, so I moved again to the stm32f1.

BUT: I still want to use 328p with the Ili9341 where ideal. Having compressed fonts, and flash chips, makes that SO much more possible. And compression and flash will make the stm32 ever more useful.

- I see some of your ili9341 work is ported in that stm32 arduino repository, though i found the ported ili9341due library there is much faster than yours on all operations but fillscreen and fill rect, interestingly. Your library still seems to be the king for 328p, if using f_as_t mode.

- So, in answer to your question on what i'm using:, ili9341 for 328p and stm32. And then any of the other ones i mentioned, like that480x320 one you got. So you could/should put it in your lib for the illi9341 on AVR at least, and It would be appreciated in the stm32arduino repository illi9341 drivers too..

Here's an idea: at some point, you/I/we port it into the gText library that the ili9341due uses. that appears to be a nice library/font stardard to use, if we're going to have the space savings to be a little more indulgent with font choice. It has many fonts already imported, tools to import, etc.. Or is that lib too bulky/cumbersome for your taste?

I'm super happy with the discovery/use of the maple mini, often wanting more power/space than a 328p, but not wanting to budget the bulkier $13 mega2560+ into everything that could use it..

When it starts approaching the price of the cheapest android phone, you have to rethink what you're doing programming hardware. After all; for $40 or $50, you get a 700mhz+ arm, with battery, high-res capacitive touch screen, wifi, bluetooth, storage, gsm, etc. and mature development tools and community. Could interface to this from your mcu a number of ways. So i recon $20-25 is the sanity check level for MCU+TFT for arduino..

Thanks again for your work. this is great, if there's anything i can do to help you develop or refine it, let me know.

Bodmer (author)intriq82015-06-02

The HX8352-A display in the link does not appear to have the 5V to 3.3V logic level translators so would need an extra board. I have a couple of these:

http://www.ebay.co.uk/itm/301454650227

These use the HX8357 driver and I created a driver library for it for the Arduino Mega. These use HC245 level converter IC's so work well with SD Cards. There is a empty footprint for a SPI FLASH device too that looks Winbond compatible! It sits close down on the Mega which means the board must be dismounted to get at the SD Card and the other Mega pins are not easily accessible. But it makes a nice cheap TFT assembly with a Mega clone. Banggood sell then with a Mega clone for about £11:

http://www.banggood.com/Mega2560-R3-Board-With-USB...

I also have the 400x240 display you mention, it has resistor based level converters. The empty FLASH device footprint does not look Winbond compatible though. Typically these screens are advertised with the wrong driver but are ILI9327 based. I have adapted/created a simple Touch library for it (as the UTFT Utouch library has reliability issues with that display). I am not a fan of the cheap resistove touch screens though as the plastic on the screen is easily marked.

I see we think along the same lines, I have a cheap android phone that has never been used as a phone... instead I use the WiFi, Bluetooth, web browser and touch screen features to compliment my Arduino projects!

I will tidy up the RLE sketches atc and adapt a ILI9341 library to display the RLE fonts. It may take me a week or two to get this done as I am rather busy with paid work at the moment!

OK I think I have probably covered all your questions!

TTFN

uhclem (author)Bodmer2015-07-24

Where is your driver for the HX8357? I have one mounted to a Due, where performance is pretty bad considering what the Due is capable of.

Thanks!

Bodmer (author)uhclem2015-07-26

You could try the attached. This is a 16 bit interface library that I use with a 480x320 display and a Mega. It might not work for you though.

uhclem (author)Bodmer2015-07-26

Thanks! I'll try it.

intriq8 (author)Bodmer2015-06-01

I want to convert the many big/full fonts from the uTFT or gText format to this new format. Any thoughts on how I/we should approach that?

Bodmer (author)intriq82015-06-02

I looked at a few options when I wanted to create a library that was small for the UNO/328, for example true type font converters and re-using fonts from other libraries but then I came across "Cosmic Void's" font editor software:

https://forum.crystalfontz.com/showthread.php?3619...

This is a little flaky and crashes when editing sometimes :-(... but the really nice feature is it encodes the fonts into a convenient C code friendly format. This is configurable and the output is a nice individual character array text file format that is in an almost ready to use form (minor edits needed) to compile with the Arduino IDE. It also creates the proportional spacing width table for each character too and the font related variables (height etc). This makes things so much easier! It is also quite human readable and permits individual characters to be replaced as each character is an array with the ASCII code in the array name.

The software has some fonts included, I just wanted a proportional space Helvetica style non-serif font which fortunately it has in the set in a few different sizes, bold, italic etc. It will also produce outline character fonts.

As I am familiar with that software (and the minor edits needed) I can now create a new font file and test it with a TFT display in about 30 minutes. So... to answer the question, now I have gone down that route I am not sure I would bother to convert fonts from other libraries, though I can see why this might be of general interest.

Bodmer (author)intriq82015-06-14

Thanks for your patience.

I have released a library for you to try. See Step 8 of my Instructable:
"Arduino TFT display and font library"

The library with Run Length Encoded fonts and examples is attached to that step as a Zip file.

TTFN

Bodmer (author)intriq82015-05-11

I tried Run Length Encoding the fonts with a simple "normal" run length method but the results were not as good as hoped. Compression ratios in the order of 2 to 3 were obtained. Here is an edited report produced by the sketch:

Font 2 RLE
Font count = 1568 bytes
RLE count = 2534 (bigger as there are so few "long" pixel runs!)

Font 4 RLE
Font count = 6422 bytes
RLE count = 4655
1767 bytes saved with 7 bit RL counter
2032 bytes saved with 3 bit RL counter

Font 6 RLE
Font count = 2976 bytes
RLE count = 1481
1495 bytes saved with 7 bit RL
1048 bytes saved with 3 bit RL

Font 7 RLE
Font count = 2208 bytes
RLE count = 1275
933 bytes saved with 7 bit RL
721 bytes saved with 3 bit RL

Font 8 RLE
Font count = 6150 bytes
RLE count = 2085
Difference = 4065

As would be expected the bigger fonts have better compression ratios as they have much longer pixel runs.

But I now have a better method to try, which is a hybrid method where short runs are stored as raw bytes and only longer pixel runs are stored run length encoded.

I also have a working Arduino sketch for compressing bigger image bitmaps stored on an SD
card with the new RLE hybrid method, and for displaying them afterwards. That is currently written as
more of a demo as the software has some debug stuff in it and has not been optimised yet, but I am getting compression ratios in the range 4:1 to 10:1 for suitable images/icons. I have yet to adapt the same method to the fonts.

I have some 1Mbyte SPI FLASH chips on order too as I see this as a potential method for storing the compressed fonts and icons, this will avoid the filing system overheads imposed by using SD Cards.

So it is a "work in progress"... continue to watch this space " "!

intriq8 (author)Bodmer2015-06-01

Excellent! I have been working on this a bit too, on paper. My rough calculations that 3bit can work for the small fonts appear confirmed by your tests, sweet.

My studies brought me to the same conclusion : a flag for literals could be ideal. Also:

1. Did you consider Huffman coding , a tree per font, to further optimise the encoding of run lengths? Do you think there's an effiecient way to decodethe huffman values without impacting render speed severely? It would of course mean you'd have to pack the stream with all the different bitlengths, it would no longer be on neat 4 or 8 bit (3+1 and 7+1) boundaries. But the huffman encoded values have that surprising unambiguous quality as they decode.

How about something like, for example, generate a lookup table of the huffman coding for a font:

7bits, so 128x2 byte array, costing 256bytes,
or 3bits for small fonts; 8x2 byte array costing 16 bytes, stored as part of the font.
- Do you think that huffman encoding would be worthwhile, if implemented optimally?
- Do you know the proper/better way to store a huffman tree for decoding values?

- When you look at the run lengths, have you noticed a distribution trend?

[Looking the structure of a font, it would stand to reason; a lot of the stems/risers are the same width, and there are many cases of same-length black wraparound to the risers.]

[I thought I saw a nice uneven distribution on the few small chars i was playing with on paper. ...Ive really got to move this to code. I'll look at your library....]

2. Another one I saw was to use the flag bit to indicate a run of alternating bits / vs same bits. This isn't too useful for fonts I guess. Might be useful on a bitstream with many alternating runs.

3. LZSS? or something LZ ish? I saw someone made a lightweight LZ library for arduino..

4. ..or anything along the lines of the technique of creating a running dictionary, which optimises for longer words as it goes.

i.e. it starts with a dictionary of minimum data width (so in our case just the entries 0 and 1., looks the the next unknown sequence in the input stream, e.g.;

input 0 = match, so look at next bit:
next bit 0 again, no match for 00, so add to dictionary. and so on, with limits.

Could then either just encode/output the 00, add 00 to the dictionary, and store the whole final dictionary, or you can encode the 0, then add 00 to the dictionary, and the use the decode-time creation of the dictionary by the same rules method, which would have to be per char, but would be pretty small dictionary..might still work.

That type of scheme, it seems to me, could be quite good for the kind of patterns in the font data, especially applied across the whole thing.

5. "I have some 1Mbyte SPI FLASH chips on order " mmm, i have 4mbyte winbond ones on order, 50c each delivered, same price as those 1Mbyte Q80s, which i mistakenly bought first ;)

" I see this as a potential method for storing the compressed fonts and icons, this will avoid the filing system overheads imposed by using SD Cards."

-YES.!!! exactly. not to mention they're way cheaper than an SD card, and you can use them for audio, other program data, data logging, etc..

If this "font compression on arduino" thing is done well, this should be incorporated in all arduino font/gfx libs, as it is very sorely needed.

I'm keen to contribute however i can.

Bodmer (author)intriq82015-06-02

Wow, so many things to discuss!

Using literal is fonts only gave better compression for small fonts and is a pain to render at speed because the original idea behind using RLE is that we get a raster scan feed immediately as an output without any processing algorithms needed. So it is fast to render, and this indeed is the case. With a 16 bit interface font rendering to screen achieves over 1 Megapixel per second as it is only necessary to set the 16 bit colour at the port and then generate the N (where N is run count) write strobes. This means a large (48 point) font character can be drawn in a few milliseconds when pulled from the Arduino FLASH memory.

There is a lot of scope for further compression, in particular there are a lot of repeating sequences, for example for the letter "l" but it comes down to what I need for my own projects and I find the basic RLE is good enough and I like to keep things simple! Indeed I worked out that on some projects the best way to reduce font space is to only include the characters I use rather than things like "#^&" etc, so at the moment I am looking at a simpler way of including font character subsets (this is already done for large fonts as I only included numerals and the characters I wanted like ":,a,m,p" for time displays.) because even the word "Hello" in a large will not fit on the screens I like to use due to lack of screen real estate... but I do like to display numerals large as they represent sensor readings.

I have implemented RLE with literals for 16 bit graphics images, as a test I extracted the 13 frames as BMPs from the GIF below (GIFs are nicely compressed!), reduced the x and y by 50% to get images 122 x 93 pixels (30KB each BMP, 23KB for 16 bit raw), encoded using my image RLE software to ~3KBytes per frame, saved the 13 images to FLASH in an Arduino Mega and plotted to TFT (16 bit parallel interface) as an animation... which then ran much too fast at 11ms per frame (90 frames per second)! This means the simple image (clearly most of the area is just one colour and hence good for RLE, but the golfer image was antialiased) was being pulled from flash AND plotted at over 1Megapixel per second. In the end I put a 150ms delay between each frame to get the animation running at roughly the right speed.

As you say the multi Megabit SPI FLASH chips are cheap, especially from Aliexpress etc. At the moment I am "playing" with the 1Mbyte chips in 8 pin DIL format for a project but will be getting larger capacity cheaper SOIC ones to fit on the vacant spot on the back of some of my TFT displays.

intriq8 (author)Bodmer2015-06-04

Yes, so many points ;)

Thanks for all your replies!

intriq8 (author)2015-06-01

Question: Why no F_AS_T for mega?

It's direct port manipulation right? So the port/pin masks are different for the mega... What is it that i am naively overlooking when i think that its just a matter of looking up the relevant mega port/pin direct manipulation equivalents and doing a search-and-replace? Does it work differently?

Would be even more handy if it worked fast with mega too. [Though cooler than mega would be if you optimised for stm32duino/maplemini.]
On uno it's only faster than the current adafruit one when f_as_t mode is enabled.

Bodmer (author)intriq82015-06-02

As you say this is possible, the simple reason is that I have not needed this facility myself, I am using 16 bit parallel interfaces on my Mega projects which can clear the screen at 2 Megapixels per second (we only need to setup the 16 bit colour then generate write strobes fast). The SPI on these Mega projects is just used for SD card and SPI FLASH access. As the display is about the same size as the Mega the large PCB is not an issue. The libraries posted here were really developed just for my own Arduino UNO/Micro pro projects (Micro pro clones from China are only about $2 each...) and hence the intent was not to develop an "official" library. So the library features are just stuff I need for my projects really. The STM32 is of interest but I have not actually got around to buying any boards yet...

intriq8 (author)Bodmer2015-06-04

heheh, sorry, didn't mean to come off all demanding, was just curious what it involved, as I may be able make the changes myself.
Ok, well if it does work the way i assume, if i do update your library for direct port manipulation on the mega, I'll be sure to post back the changes. ;)

Ah, so the work of yours i saw over at stm32duino was "ported" over by someone..

gdmuscle (author)2015-04-20

Has anyone been able to get animation on the TFT like gif animation going?

Bodmer (author)gdmuscle2015-04-27

The UNO can pull pixels off the SD card and draw on screen about 100 pixels per millisecond. An animation that updates at 25 frames per second gives 40 milliseconds per frame, in this time the UNO could draw 100 x 40 pixels, thus a set of raw images of 65 pixels square would animate quite well. The G IF images are compressed and the UNO does not have the processing power to decompress them and draw to screen quickly, thus the only simple way of creating an animation would be to create a set of raw images, each being one frame of the animation.

gdmuscle (author)Bodmer2015-04-27

Oh ok, so to do this don't put a time delay between the images displayed on the SD bitmap images?

Bodmer (author)gdmuscle2015-04-27

Yes, correct. A delay would only be needed to slow down the animation frame rate.

gdmuscle (author)Bodmer2015-04-28

Yeah tried that not much of a smooth display though got it working using bmp files not sure if the original tft2bmp is fast enough.

gdmuscle (author)2015-04-28

The strange thing is that my display shows nothing yet there is something on there. I tested the Sd card reader it's reading fine but for some odd reason the test images don't show?

Bodmer (author)gdmuscle2015-04-28

Do you have the LED back light working OK?

gdmuscle (author)Bodmer2015-04-28

Yeah I hooked it up to Pin 5 high output also tried to hook it directly to 3.3v nothing. The picture shows the colour grey swipe down left right but no bmp or raw images.

RémiG (author)2015-04-01

Hello,

I try this lib for show text, but i can't run it, y have a lot of error with SPCR, SPDR, SPIF varibale not declared :(

C:\Program Files (x86)\Arduino\libraries\Adafruit_ILI9341_AS\Adafruit_ILI9341_AS.cpp:394:13: error: 'SPSR' was not declared in this scope
while(!(SPSR & _BV(SPIF)));

Thanks.

Bodmer (author)RémiG2015-04-01

These definitions are in a standard AVR header file called up during compilation. Are you using an AVR processor....!

Which IDE version and Arduino board are you using?

RémiG (author)Bodmer2015-04-01

I try on Arduino DUE which is not AVR I think

CPU : Atmel SAM3X8E ARM Cortex-M3

IDE : 1.6.2

Bodmer (author)RémiG2015-04-03

OK, I do not have DUE so cannot help adapt the library for that platform. You may be able to get help on the Arduino forum as the problems in porting to the DUE are likely to be common with other libraries and sketches. Sorry but until I get a DUE I can not help!

RémiG (author)Bodmer2015-04-03

Ok, no probleme i will check on arduino forum and come back if i have an answer.

About This Instructable

53,425views

31favorites

License:

More by Bodmer:Arduino - TFT display of icons and images from FLASH memoryArduino - TFT display of bitmap images from an SD CardArduino analogue 'ring' meter on colour TFT display
Add instructable to: