Most TFT displays come with an SD adapter mounted on its back, but sometimes you want to go without. When you want to store a multi-colored bitmap in the restricted FLASH memory you soon exceed the limits of its size. Even the small 1.8" display offers 160 x 128 pixels. If you choose the standard RBG format you will need 61, 440 bytes of memory. Even with the ATmega2560 you will run into problems as arrays are limited to 32, 768 bytes. When you check the data sheet of your display you might find that internally only two bytes are used for each pixel, giving 5 bits for red, 6 bits for green, and 5 bits for blue. So, if you convert the bitmap file in this way you still need 40, 960 bytes. That is why I was looking for a stronger kind of compression. At the end of the day, I came up with this file format:
Of course, there is no graphics software to convert a given picture to that format, a special software had to be written. I provide a version in Pascal (Delphi), you can easily convert it to your favourite language:
procedure TForm1.Button1Click(Sender: TObject);
var f : file of byte;
h : textfile;
x, y : integer;
r, g, b, c, d : byte;
begin
if Opendialog1.Execute then
begin
AssignFile(F, OpenDialog1.FileName);
Reset(F);
seek(f,54);
AssignFile(h, 'dest_332rgb.h');
rewrite(h);
x := 0;
y := 125;
while not eof(f) do
begin
read(f, b);
read(f, g);
read(f, r);
Image1.Canvas.Pixels[x,y] := Rgb(r,g,b);
c := (r and $E0) + (g and $E0 shr 3) + (b shr 6);
write(h,c);
write(h,',');
x := x + 1;
if x> 125 then
begin
x := 0;
y := y - 1;
read(f, d);
read(f, d);
write(h,#13);
end;
end;
closefile(f);
closefile(h);
end;
end;
The limits were set for a squared picture of 126x126 pixels. The two dummy reads near the end will be necessary as any line in a BMP file has a multiple of four bytes. The destination file will contain only the compressed data without any header information. On the Arduino side you have to decompress the data. Just move the destination file to your Arduino folder and use this code:
/*
display of compressed color bitmaps
format: rrrgggbb
*/
const byte cs = 10;
const byte dc = 9;
const byte rst = 8;
#include <TFT.h>
TFT tft = TFT(cs, dc, rst);
const PROGMEM unsigned char rawData[] = {
#include "dest_332rgb.h"
};
void setup() {
Serial.begin(115200);
Serial.println("\n" __FILE__);
tft.initR(2);
tft.setRotation(3);
tft.fillScreen(0);
int w = tft.width();
int h = tft.height();
const word ROT = tft.Color565(255, 0, 0);
tft.drawRect(0, 0, w, h, ROT);
int br = 126;
int ho = 126;
int x0 = (w - br) / 2;
int y0 = (h - ho) / 2;
int x = 0;
int y = ho-1;
int i = 0;
int s = sizeof rawData;
while (i < s) {
word c = pgm_read_byte(rawData + i++);
byte r = c & B11100000;
byte g = (c & B00011100) << 3;
byte b = (c & B00000011) << 6;
c = tft.Color565(r, g, b);
tft.drawPixel(x0 + x, y0 + y, c);
if (++x >= br) {
y--;
x = 0;
}
}
}
void loop() {}
In the Arduino UNO, it will use 23 kByte of FLASH and nearly no SRAM, so you still have plenty of memory for your main algorithms.
To demonstrate what you can expect by reducing the resolution let me show you this example:
And now what a 1.8" display actually can show:
Comments
Please log in or sign up to comment.