Writing bitmaps.

FTDI/Bridgetek EVE2 & EVE3 & EVE4 SPI TFT Series by Matrix Orbital

Moderator: Mods

Post Reply
rascalito
LCD Geek
Posts: 38
Joined: Sat Apr 18, 2020 11:22 pm

Writing bitmaps.

Post by rascalito »

Hello!

I have been playing with EVE3 for a while, and I can do basically everything that involves
drawing. Now I would like to use bitmaps. In order to understand how it works, I would like
to use a raw bitmap like this (in ARGB4444)
#define RED 0xFF00 // At this point, I suppose that the A component = F is purely opaque
#define GREEN 0xF0F0
#define BLUE 0xF00F
#define WHITE 0xFFFF

uint16 MyBitmap[] = {
WHITE, WHITE, BLUE, BLUE, BLUE, BLUE, WHITE, WHITE,
WHITE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, WHITE,
BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE,
BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE,
BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE,
BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE,
WHITE, BLUE, BLUE, BLUE, BLUE, BLUE, BLUE, WHITE,
WHITE, WHITE, BLUE, BLUE, BLUE, BLUE, WHITE, WHITE
};

So I suppose the first step is to copy the bitmap somewhere, but where? In the external FLASH? IN G RAM?

Is there a sample program somewhere that shows how to use a single bitmap?

Other question: In the EVE header files I found, there are some definitions like this:
#define RAM_G 0x0
#define RAM_DL 0x300000
These are OK, they apparently correspond to memory areas of the chip itself.

Now there is this line:
#define RAM_FLASH 0x800000

What is this? Is it RAM, or is it FLASH?

#define RAM_FLASH_POSTBLOB 0x801000

If I erase the whole flash, will it erase the BLOB part, or is there a security that prevents overwriting the BLOB part?

Thanks,

R

rascalito
LCD Geek
Posts: 38
Joined: Sat Apr 18, 2020 11:22 pm

Re: Writing bitmaps.

Post by rascalito »

Hello!

I have finally managed to write bitmaps in G_RAM and use them.
But there is something unclear at the moment.
I have written 2 bitmaps as follows:
One is a right arrow (16x16), the other is a pattern sometimes found in textiles (8x8).
The arrow is written at 0, the other pattern is written at the end of the first one,
which is 512 (16 x 16 x 2). The first image below is right, the second is not what I
intended to draw. I was expecting the second bitmap to be drawn straight.

Here is the capture of the oscilloscope SPI signals:
Without rotation:

Code: Select all

B0 25 78		//	REG_CMDB_WRITE
00 FF FF FF		//	DL start
90 60 30 02		//	Clear RGB with R=0x30, G=0x60, B=0x90
07 00 00 26		//	Clear command with (1,1,1) arguments
00 00 00 01		//	0x01000000 = Bitmap source, address = 0
10 40 00 07		//	0x07000000 = Bitmap layout. As width = 16, 2*width = 32 (0x20), shifted by 9 bits = 0x0400
10 20 00 08		//	0x08000000 = Bitmap size. last 9 bits = height = 0x10. Wid shifted = 0x20
01 00 00 1F		//	0x1F000000 = DL begin. Argument 01 = bitmap.

//	At this point, a fwe lines are added in case of an angle.

00 40 81 82		//	Vertex2II including coordinates (20,20), no handle, no cell
00 00 00 21		//	DL_END before switching to the next bitmap.
00 10 00 01		//	0x01000000 = Bitmap source, address = 0x1000
08 20 00 07		//	Bitmap layoout, dimensions = 8 x 8
08 10 00 08		//	Bitmap size, also 8 x 8
01 00 00 1F		//	0x1F000000 = DL begin. Argument 01 = bitmap.
00 80 82 82		//	Vertex2II including coordinates (20,40), no handle, no cell
00 00 00 21		//	DL_END
00 00 00 00		//	End of list
01 FF FF FF		//	CMD_SWAP
And then with rotation:

Code: Select all

B0 25 78		//	REG_CMDB_WRITE
00 FF FF FF		//	DL start
90 60 30 02		//	Clear RGB with R=0x30, G=0x60, B=0x90
07 00 00 26		//	Clear command with (1,1,1) arguments
00 00 00 01		//	0x01000000 = Bitmap source, address = 0
10 40 00 07		//	0x07000000 = Bitmap layout. As width = 16, 2*width = 32 (0x20), shifted by 9 bits = 0x0400
10 20 00 08		//	0x08000000 = Bitmap size. last 9 bits = height = 0x10. Wid shifted = 0x20
01 00 00 1F		//	0x1F000000 = DL begin. Argument 01 = bitmap.
//	Here is the rotation
26 FF FF FF		//	LOAD_IDENTITY
51 FF FF FF		//	ROTATE_AROUND
08 00 00 00		//	Half of the width (center of the rectangle)
08 00 00 00		//	Half of the height
00 20 00 00		//	0x2000 is precisely 1/8 of a turn, therefore 45 degrees
00 00 01 00		//	Scale (0x00010000 is 65536, therefore no change)
2A FF FF FF		//	Set the matrix
//	End of rotation
00 40 81 82		//	Vertex with coordinates, no handle, no cell
00 00 00 21		//	DL_END
00 10 00 01		//	Bitmap source at 0x1000
08 20 00 07		//	Bitmap layout, dimensions = 8x8
08 10 00 08		//	Bitmap size, also 8x8
01 00 00 1F		//	0x1F000000 = DL begin. Argument 01 = bitmap.
00 80 82 82		//	Vertex2II including coordinates (20,40), no handle, no cell
00 00 00 00		//	End of list
01 FF FF FF		//	CMD_SWAP
I'm not sure of what happens, but here is one question: if I set a rotation for the first bitmap,
will it also rotate the second one? Is there an easy way to cancel a rotation when the bitmap is done?
At present, the rotation I have set rotates from the center of the image, using CMD_ROTATEAROUND,
so if this rotation stays enabled, it will rotate the small bitmap around (8,8), which is the center of
the first one, but the corner of the second one.

Thanks for any hint.
IMG_4394.jpeg
IMG_4394.jpeg (95.86 KiB) Viewed 1582 times
IMG_4396.jpeg
IMG_4396.jpeg (90.11 KiB) Viewed 1582 times

rascalito
LCD Geek
Posts: 38
Joined: Sat Apr 18, 2020 11:22 pm

Re: Writing bitmaps.

Post by rascalito »

Hello!

I think this will be the last one of the series...
I got it (more or less)!
In fact, I partly replied yesterday to my own question. The rotation setup apparently
stays set until you tell the screen to unset it. That's the role of LOADIDENTITY.
Keep a variable somewhere that remembers if a rotation has been made or not, and if
there was a rotation, then load identity again.
Now the magic of this screen is that with a few instructions, you can fill a rectangle
with a given pattern.
As I like software that does what it claims and not more, my API looks like this:

// Draw a simple bitmap
void EveLCD::DrawBitmap(Rect Frame, uint32 gram_address, uint16 angle);

// Draw a filled rectangle with a bitmap pattern
void EveLCD::FillRectangle(Rect Frame, Size Tile, uint32 gram_address);

NB: Rect is a simple class with x, y, w, h with a few useful methods.
Size is another class with only w and h. Similarly, there is also a Point class with x, y.

The code for the images below looks as follows:

Code: Select all

void EveLCD::Test(void) {
    Rect Frame(0, 0, 800, 480);			// Rectangle for the whole screen
    Rect ArrowFrame(20, 20, 16, 16);		// Rectangle for the pink arrow
    Size Tile(8, 8);				// Size of the tile
    DrawBitmap(ArrowFrame, PINK_ARROW); 	// PINK_ARROW is the address of data in G_RAM
    Rect.InsetBy(50, 50);			// Recalculates the rectangle with a constant margin on all borders
    FillRectangle(Frame, Tile, BW_PATTERN);	// BW_PATTERN is the address of data in G_RAM
}
And here is the result. Très chic!

R

IMG_4397.jpeg
IMG_4397.jpeg (83.83 KiB) Viewed 1579 times
IMG_4398.jpeg
IMG_4398.jpeg (69.68 KiB) Viewed 1579 times

Raquel
Matrix Orbital
Matrix Orbital
Posts: 808
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Re: Writing bitmaps.

Post by Raquel »

Hello Rascalito,

Thank you for posting on the forum.
And thank you for sharing your findings.

I am sure this will be helpful to people out there looking at doing the same thing.
You are right, very stylish graphics!

Best Regards,
Raquel
Raquel Malinis
Design and Development
Matrix Orbital

Post Reply