Video showing 1st cut of TFT driver library

Finally got the 1st cut of the TFT code working with streaming on a Mega 2560.

The code works on Mega 2560, Uno and Due. This actual TFT will not work on a UNO as it has a 16 bit parallel interface.

The video description has more details.

Demo also has a modified version of sdfat which works on the Due.

Have added 16 bit bitmap support last night. Works real well and because of the converter program and the way it saves... have native 16 bit with transparent pixels if desired.

Ran into a small bug... which is what testing is about. Originally written for just the Uno which is frugal on memory I made 4 variables that are stored with each glyph uint8_t... when I went to test a 320*240 image... dohhhhhhhh :money_mouth_face: .

I was going to just make the 4 variables int 16's but then thought of a better way. (since I have to break the code anyway).

In the header add a flag.

uint8_t m_adjust size;

0 = no offsets (minx maxx, miny, maxy are all the default dimensions in the header... if multiple they're all the same.)

1 = has offsets and they use 1 byte each.
2 = has offsets and they use 2 bytes each.

This will mean a small font on a small device will not incur all the overhead for each glyph.

Also... at the moment 0 degree rotation and 270 is supported which are currently called landscape/portrait. This is going to get changed to 0, 90, 180 and 270 and rename appropriately.

Made major improvements to both speed and the simplicity.

Program that exports images and fonts now supports > 255 width/height bitmaps and had improvements to the optimization when creating the binary files.

Vertical lines are now optimized and as fast as horizontal lines. Found they were dead slow.

Implemented hardware scrolling, wake and sleep.

16bpp images now supported and work real well.

Added something I call "virtual screen blit".

Virtual screen blit
Basically I create a 1bpp virtual screen (as the library supports this) and render text to it, render lines, etc. However, instead of sending the rendered pixels to a Nokia5110 or some other 1 bit device I send to the LCD as a VERY FAST blit as the byte order of the virtual screen is the same as any bitmap.

In the example I render some test text to a virtual screen... then later I can render this. The size of the virtual screen can be resized easily as long as the new dimensions fit in the original byte allocation.

Because of the way TFT's operate and the overhead of setting and resetting x,y coordinates the virtual screen blit only sets this once as the entire blit is in a single window with very few instructions in the inner loop.

cDIB_TFT_SSD1289_16_16bpp g_dib;
cDIB_virtual_1bpp g_dib2;

void setup()
{
  Serial.begin(9600);

  sdCard.init(SS_PIN, SPI_FULL_SPEED); 
  sdCard.cd("bmp"); 

  g_dib.begin(); // init lcd with defaults as on shield 
  g_dib2.begin(20 * 8, 22); // allocate a "virtual screen"

  
  g_dib2.clearScreen();
  g_dib2.setFont(&font_small);
  g_dib2.setFontSpacing(1);  
  g_dib2.setFontVariableWidth(true);
  g_dib2.drawText("01234567890 test TEST"); 
    
  g_dib.setRotation(0);

  g_dib.setFont(&font1);
  g_dib.setFontSpacing(1);  
  g_dib.setFontVariableWidth(true);
}

// in memory blit with virtual screen

void draw_vscreen(int stage)
{
  for (int i = 0; i < 400; i++)
  {
    g_dib.setColorFG(g_dib.getColorKnown(i));
    g_dib.setColorBG(g_dib.getColorKnown(400 - i));
    g_dib.drawBlit( (i & 63), (i * 20) % ( g_dib.getClipper_y2() - g_dib2.getHeight() - 5 ), &(g_dib2.m_bmp));
  }
   
  g_dib.setColorBG(DIB_COLOR_BLUEVIOLET);  
}

Still plodding along with this. Going quite well. Implemented 4 bit grayscale with the rl encoding as it's very compact and easy to uncompress.

The inner part of the drawBitmap routine is large... very large as internally it has code specific to

device color depth + input source color depth + clipping + mode

At the moment color depth 1 or 16, input color depth = 16, 1 or 4, clipping is either 0 or 1 and mode is DIB_BLIT_OR or DIB_BLIT_STORE.

I combine a few variables into a unique 16 bit code from the above and it drops into the correct routine.

if (minx < m_clip_x1 || miny < m_clip_y1 || maxx > m_clip_x2)
  {
    draw_code = 1; // some sort of clipping
  }
  else
  {
    draw_code = 0;
  }
  
  draw_code |= (mode << 1) | (m_bpp << (1 + 3)) | (bmp->m_bpp << (1 + 3 + 6));

The blocks of code themselves have something like...

 case  (0) | (DIB_BLIT_STORE << 1) | (1 << (1 + 3)) | (1 << (1 + 3 + 6)) : // 1 -> 1   STORE

I have about 80% of the combinations done... end result is code that is tightly optimized for each combination. Found very early on that generalized code with too many if's etc in the low level routines resulted in ... well code that worked but with massive performance loss.

The copy of sdfatlib I used... I found out was very old and didn't support the Due. I will have to see if the latest version is any faster. I get about 290 K bytes / sec read speed on it with the Due. The buffer size is also a hard coded 512 which I think may have changed.