ST7789_t3 (part of ST7735 library) support for displays without CS pin

@mjs513 (and all),

I did a first pass at trying to preserve the overlap pixels while doing GFX Fonts and opaque.

To make it easier to see, I hacked up my output test, like:
Code:
tft.setFont(&FreeMonoBoldOblique12pt7b);
  printTextSizes("AdaFruit");
  if (fOpaque){
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("A");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("d");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("a");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("F");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("R");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("u");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("i");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.println("t");
    tft.setTextColor(ILI9341_WHITE, use_fb ? ILI9341_BLACK : ILI9341_RED);
  }
  else tft.println("AdaFruit");
So far I have only done the harder part (not Frame buffer)
Looks like it is working pretty well...
IMG_0910.jpg

The Frame buffer case should be pretty easy. If in that pixel range, if we are going to set to BG color and current pixel is NOT the previous FG color then update it to new BG color...
 
Looks good enough to me! Ship It!

Ok just sent you a PR to the master branch. Think it has all your other changes as well - sorry forgot to set it up for DMA-fonts branch. - never mind just saw what you did - already updated
 
@mjs513 (and all),

I did a first pass at trying to preserve the overlap pixels while doing GFX Fonts and opaque.

To make it easier to see, I hacked up my output test, like:
…...
So far I have only done the harder part (not Frame buffer)
Looks like it is working pretty well...
….

The Frame buffer case should be pretty easy. If in that pixel range, if we are going to set to BG color and current pixel is NOT the previous FG color then update it to new BG color...

Looking good - should be interesting to see what happens with my changes incorporated
 
@mjs513, your changes are in! Need to now reincorporate the changes for supporting the overlapping chars.

Should have that done sometime this morning.... After coffee!
 
Morning @KurtE

On my 3rd cup of coffee so far this morning. Got Adafruit Fonts sort of working on the ILI9488 but not opaque nor with Adafruit with Opaque nor framebuffer. Think I have to implement more stuff from the ILI9341 lib like writeRect8BPP etc.

Also to get it working I had to change framebuffer to int16 to account for pixel_row being uint16.

Could be we are also doing write16color(pallet[*pbfpxl]) or something like that.

Now back to playing
 
@mjs513 - I will try to take a look later...

Right now, I have my code sort of merged back in. Did find a few more interesting things to fix...

That is right now the Opaque code is NOT working properly (I think) if a character has an xOffset < 0... That is the character starts drawing into the space of previous character.

I turned back on (plus a little more stuff) the debug code that printed some font info when you select a new font...

Code:
Set GFX Font(60001298): Y: 24 -16($) 6(_) X: -1(_) 4(M)
Set GFX Font(600012a4): Y: 29 -16($) 6(g) X: 0( ) 1(a)
For the two fonts I included, it is showing that there is at least one character with xOffset = -1
And at least one charcter that extends 4 pixels (times fontsize_x) into the following character...

So in the case of the -1, (Assuming start part not clipped off, I need to start my output 1 pixel earlier.
Which also means that in this case when I output that one pixel column if the character being output is not setting that bit for FG and the Previous character output did not set that pixel to FG, it should use the previous characters BG to output...

Frame buffer update is simple as I simply don't touch that memory location...
 
@KurtE

Thanks for checking - one symptom in non-FB is that instead of turning the background black it turns the text black - argh.....

Sounds like you are making a lot of progress but the little gotchas are getting you. Good luck
 
@mjs513 (and all who wish to play)

I just updated the ILI9341_t3n with the GFX Font Opaque code to hopefully reasonably handle overlapping characters, including the xOffset < 0...

Again I updated the test code for drawing the text screen to in this case alternate colors for the characters in Opaque mode...
Code:
void drawTextScreen(bool fOpaque) {
  SetupOrClearClipRectAndOffsets();
  tft.setTextSize(1);
  uint32_t start_time = millis();
  tft.useFrameBuffer(use_fb);
  tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
  tft.setFont(Arial_28_Bold);
//t  tft.setFont(Arial_40_Bold);
  if (fOpaque)
    tft.setTextColor(ILI9341_WHITE, use_fb ? ILI9341_BLACK : ILI9341_RED);
  else
    tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(0, 5);
  tft.println("AbCdEfGhIj");
#if 0
  tft.setFont(Arial_28_Bold);
  tft.println("0123456789!@#$");
  tft.setFont(Arial_20_Bold);
  tft.println("abcdefghijklmnopq");
  tft.setFont(Arial_14_Bold);
  tft.println("ABCDEFGHIJKLMNOPQRST");
  tft.setFont(Arial_10_Bold);
  tft.println("0123456789zyxwvutu");
#endif
  tft.setFont(&FreeMonoBoldOblique12pt7b);
  printTextSizes("AdaFruit_MB_12");
  if (fOpaque){
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("A");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("d");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("a");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("F");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("R");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("u");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("i");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("t");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("_");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("M");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("B");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.print("_");
    tft.setTextColor(ILI9341_RED, ILI9341_BLUE);
    tft.print("1");
    tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
    tft.println("2");
    tft.setTextColor(ILI9341_WHITE, use_fb ? ILI9341_BLACK : ILI9341_RED);
  }
  else tft.println("AdaFruit_MB_12");
  tft.setFont(&FreeSerif12pt7b);
  printTextSizes("FreeSan12");
  tft.println("FreeSan12");
  tft.println();
  tft.setTextSize(1,3);
  printTextSizes("Size 1,3");
  tft.println("Size 1,3");
  tft.setFont();
  tft.setCursor(0, 190);
  tft.setTextSize(1,2);
  printTextSizes("Sys(1,2)");
  tft.println("Sys(1,2)");
  tft.setTextSize(1);
  printTextSizes("System");
  tft.println("System");
  tft.setTextSize(1);
 

  tft.updateScreen();
  DBGSerial.printf("Use FB: %d OP: %d, DT: %d OR: %d\n", use_fb, fOpaque, use_set_origin, millis() - start_time);
}

I think I am sort of done with this for now... Unless I get inspired to do more, like speed up the Transparent text output code ;)

That is this code:
Code:
    if (textcolor == textbgcolor) {

	    // Serial.printf("DGFXChar: %c %u, %u, wh:%d %d o:%d %d\n", c, cursor_x, cursor_y, w, h, xo, yo);
	    // Todo: Add character clipping here

    	// NOTE: Adafruit GFX does not support Opaque font output as there
    	// are issues with proportionally spaced characters that may overlap
    	// So the below is not perfect as we may overwrite a small portion 
    	// of a letter with the next one, when we blank out... 
    	// But: I prefer to let each of us decide if the limitations are
    	// worth it or not.  If Not you still have the option to not
    	// Do transparent mode and instead blank out and blink...

	    for(yy=0; yy<h; yy++) {
	        for(xx=0; xx<w; xx++) {
	            if(!(bit++ & 7)) {
	                bits = bitmap[bo++];
	            }
	           [COLOR="#FF0000"] if(bits & 0x80) {[/COLOR]
	                if((textsize_x == 1) && (textsize_y == 1)){
	                    drawPixel(cursor_x+xo+xx, cursor_y+yo+yy, textcolor);
	                } else {
	                fillRect(cursor_x+(xo+xx)*textsize_x, cursor_y+(yo+yy)*textsize_y,
	                      textsize_x, textsize_y, textcolor);
	                }
	            }
	            bits <<= 1;
	        }
	    }
    	_gfx_last_char_x_write = 0;
	} else {
Which in Frame buffer mode probably would not make a difference.
But suppose we detect things like:
if (Xbits left to output >= 8 && bits == 0xff) do one fillRect for 8 logical pixels
else if (xbist left to output >= 7 && ((bits &0xfe) == 0xfe)) output 7 logical pixels...
 
@mjs513 - Thanks,

Oops did I say I was done ;) I just pushed up a change to the Transparent GFX font output, where I try for 8 pixels, 4 3 2 1...
To try to combine outputs... Could go fancier, but...

I added a new GFX font output page... To time...
Code:
void drawGFXTextScreen(bool fOpaque) {
  SetupOrClearClipRectAndOffsets();
  tft.setTextSize(1);
  tft.setCursor(0, 10);
  if (fOpaque)
    tft.setTextColor(ILI9341_WHITE, use_fb ? ILI9341_BLACK : ILI9341_RED);
  else
    tft.setTextColor(ILI9341_WHITE);
  uint32_t start_time = millis();
  tft.useFrameBuffer(use_fb);
  tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
  tft.setFont(&FreeMonoBoldOblique12pt7b);
  tft.println("MonoBold");
  tft.println("ABCDEFGHIJKLMNO");
  tft.println("abcdefghijklmno");
  tft.println("0123456789!@#$%^&*()_");
  tft.setFont(&FreeSerif12pt7b);
  tft.println("Serif12");
  tft.println("ABCDEFGHIJKLMNO");
  tft.println("abcdefghijklmno");
  tft.println("0123456789!@#$%^&*()_");
  tft.updateScreen();
  tft.setTextSize(1);
  tft.setFont();
  DBGSerial.printf("Use FB: %d OP: %d, DT: %d\n", use_fb, fOpaque, millis() - start_time);
}
Which in previous test program I added the 'g' command to run this one...

The page has changed a little since I timed it with the pre-changed code, but the timings are probably still pretty close.
Before change: With FB: 37ms without FB 68ms
With this change: With FB: 37 without FB 51ms

So not a giant win, but will take it! Now I am done! ;)
 
@KurtE

I created a separate branch for this one: https://github.com/mjs513/ILI9488_t3/tree/Adafruit_Fonts

Note this doesn't have the latest changes that you just posted to the ILI9341_t3n repository though. Weird stuff - may have messed something up going back and forth. Not going to say what I think it is since usually I am wrong :)

EDIT: Ok - missed your update in post #237. Figured you would go and play more before you were done.
 
@mjs513... May have to wait until morning... Have some other stuff need to do this evening...
 
@mjs513 - Good morning...

Will take a look soon (I hope)... Yesterday afternoon I thought I would try something closer to the namesake of this thread and port the code back over to st7735_t3, which I have done, but now I am debugging a hang.

It will update the text screen once, and if you re-enter the text screen a second time it hangs! So added/re-enabled a bunch of debug output code...
First time I enter the draw text screen I have the data output:


Code:
Enter drawTextScreen
After Fill screen
After Set font
[COLOR="#FF0000"]SysFont(0,5): SPL:42  Rect(0, 5, 42 8)[/COLOR]
After print Text sizes
Arial(0,13): SPL:79  Rect(1, 13, 76 29)
0123456789(79,13): SPL:160  Rect(80, 13, 158 21)
Set GFX Font(60001298): Y: 24 -16($) 6(_) X: -1(_) 4(M)
AdaFruit(0,49): SPL:110  Rect(0, 47, 110 15)
DGFX_char: A (0,49) : 15 14 14 24 0 -1 ffff ffff 1
34433243233333444243334233442DGFX_char: d (14,49) : 14 15 14 24 2 -2 ffff ffff 1
442232243324242322232434443243DGFX_char: a (28,49) : 12 11 14 24 2 2 ffff ffff 1
4224322432433222222444434DGFX_char: F (42,49) : 16 14 14 24 0 -1 ffff ffff 1
444443322322224242222234444DGFX_char: r (56,49) : 14 11 14 24 1 2 ffff ffff 1

Note: The numbers like; 34433243233333444243334233442
Where the number of bits at a time I output in the previous char.... Did not output 1 for the normal stuff...

Then I try to draw it again, and the only debug output I get is:
Code:
Enter drawTextScreen
After Fill screen
After Set font
[COLOR="#FF0000"]SysFont(0,-1): SPL:42  Rect(0, -1, 42 8)[/COLOR]
After print Text sizes
What is interesting between these two is, marked in RED.

The difference in positions, is that the last thing output in the previous text screen was a GFX Font output.

Then we recall the dialog and we have the code:
Code:
  tft.setCursor(0, 5);
  tft.setFont();
So we set the position to (0,5), then we set the font to use the system font. The code then says oops I had an GFX font char selected, so better update text cursor by -6 which sets the Y to -1...

So can easily fix this case by swapping those two calls... But wonder why the code is hanging when -1 is used? Also wondering if I need to maybe setup the font offset code, that says something like, we only offset it when I switch the font, if we had output some characters, since the last call to setCursor?

Now back to debugging!

Will probably need to pull in whatever the fixes are here back to ili9341_t3n...

EDIT: Yes setting font first fixes hang... but now to figure out why?
 
@mjs513 - Found the hang :D Now to clean up some of my debug code:

The problem is/was the drawFastHLine and drawFastVLine functions were not updated to add the offset and to do rectangle clipping by bounds... So the -1 fell through...
 
@KurtE
Glad you got it working - making progress on the ILI9488 as well - got framebuffer to work with Adafruit Opaque (had to change to using color_index). Now to see if I can get some of the other issues resolved.

EDIT: Major progress :) Simple change fixed most of it - but still have a problem when switching back to our font after using Adafruit font with background. I will post the updated changes

EDIT: here is the link: https://github.com/mjs513/ILI9488_t3
 
@KurtE

Ok will give it try - almost done with resolving background on 9488. Think I figured out the problem. EDIT: then have to incorporate you last set of changes for overlapping fonts :)

When we go from using tft.setFont(gfxFont); back to the glc font tft.setFont(); it doesn't now what to do in the 9488 code base. If I specify the glc font it works fine. Don't know what to do with that one.
 
@mjs513 - Will take a look...

Just put up a PR back to you on ST7735_t3... https://github.com/mjs513/ST7735_t3/pull/5

Probably needs some more testing. My test case right now only does the Frame buffer on mode...

Must be doing something wrong. Using the following sketch with my 320x240 st7789 but seems to only work when FB = 0?
Code:
#include <Adafruit_GFX.h>    // Core graphics library
#include <st7735_t3_font_Arial.h>
#include <ST7735_t3.h> // Hardware-specific library
#include <ST7789_t3.h> // Hardware-specific library
#include <SPI.h>
#include <Fonts/FreeMonoBoldOblique12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>

#define ROTATION 1

#include "SPI.h"
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)  // Teensy 4.x 
#define TFT_DC  9  // only CS pin 
#define TFT_CS 10   // using standard pin
#define TFT_RST 8
ST7789_t3 tft = ST7789_t3(TFT_CS,  TFT_DC, TFT_RST);
#define DBGSerial Serial
#else
//#define DEFAULT_PINS
//#define USE_SPI1
#define KURTS_FLEXI
//#define FRANKS_C64

#ifdef KURTS_FLEXI
#define TFT_DC 22
#define TFT_CS 15
#define TFT_RST -1
#define TFT_SCK 14
#define TFT_MISO 12
#define TFT_MOSI 7
#define DEBUG_PIN 13

#elif defined(FRANKS_C64)
#define SCK       14
#define MISO      39
#define MOSI      28
#define TFT_TOUCH_CS    38
#define TFT_TOUCH_INT   37
#define TFT_DC          20
#define TFT_CS          21
#define TFT_RST        -1  // 255 = unused, connected to 3.3V
#define TFT_SCK        SCK
#define TFT_MOSI        MOSI
#define TFT_MISO        MISO

#elif defined(DEFAULT_PINS)
#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 8
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11

#elif defined(USE_SPI1)
#define TFT_DC 31
#define TFT_CS 10 // any pin will work not hardware
#define TFT_RST 8
#define TFT_SCK 32
#define TFT_MISO 5
#define TFT_MOSI 21
#define DEBUG_PIN 13
#else
//#define TFT_DC  9
#define TFT_DC 45
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#endif
//ST7735_t3n tft = ST7735_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
#endif

#define ST7735_PINK        0xF81F
#define ST7735_ORANGE      0xFD20      /* 255, 165,   0 */
#define ST7735_PURPLE      0x780F      /* 128,   0, 128 */
#define ST7735_LIGHTGREY   0xC618      /* 192, 192, 192 */
#define ST7735_OLIVE       0x7BE0      /* 128, 128,   0 */
#define ST7735_MAROON      0x7800      /* 128,   0,   0 */


uint16_t our_pallet[] = {
  ST7735_BLACK,  ST7735_RED, ST7735_GREEN,  ST7735_BLUE,   ST7735_WHITE,
  ST7735_YELLOW, ST7735_ORANGE, ST7735_CYAN, ST7735_PINK
};

ST7735_Button button;

// Let's allocate the frame buffer ourself.
DMAMEM uint16_t tft_frame_buffer[240 * 320];

uint8_t use_dma = 0;
uint8_t use_clip_rect = 0;
uint8_t use_set_origin = 0;
uint8_t use_fb = 0;

#define ORIGIN_TEST_X 50
#define ORIGIN_TEST_Y 50


void setup() {
  while (!Serial && (millis() < 4000)) ;
  DBGSerial.begin(115200);
  //DBGSerial.printf("Begin: CS:%d, DC:%d, MOSI:%d, MISO: %d, SCK: %d, RST: %d\n", TFT_CS, TFT_DC, TFT_MOSI, TFT_MISO, TFT_SCK, TFT_RST);

  tft.init(240, 320);
  tft.setFrameBuffer(tft_frame_buffer);

  tft.setRotation(ROTATION);
  tft.fillScreen(ST7735_BLACK);


  button.initButton(&tft, 200, 125, 100, 40, ST7735_GREEN, ST7735_YELLOW, ST7735_RED, "UP", 1, 1);

  drawTestScreen();
}

void SetupOrClearClipRectAndOffsets() {
  if (use_clip_rect) {
    tft.setClipRect();  // make sure we clear the whole screen
    tft.setOrigin();    // make sure none are set yet

    tft.fillScreen(ST7735_LIGHTGREY);

    // Now lets set origin.
    if (use_set_origin)
      tft.setOrigin(ORIGIN_TEST_X, ORIGIN_TEST_Y);
    int x = tft.width() / 4;
    int y = tft.height() / 4;
    int w = tft.width() / 2;
    int h = tft.height() / 2;
    tft.drawRect(x, y, w, h, ST7735_ORANGE);
    tft.updateScreen();
    tft.setClipRect(x + 1, y + 1, w - 2, h - 2);
    delay(250);

  } else {
    tft.setClipRect();
    if (use_set_origin)
      tft.setOrigin(ORIGIN_TEST_X, ORIGIN_TEST_Y);
    else
      tft.setOrigin();
  }
}


uint16_t palette[256];  // Should probably be 256, but I don't use many colors...
uint16_t pixel_data[2500];
const uint8_t pict1bpp[] = {0xff, 0xff, 0xc0, 0x03, 0xa0, 0x05, 0x90, 0x9, 0x88, 0x11, 0x84, 0x21, 0x82, 0x41, 0x81, 0x81,
                            0x81, 0x81, 0x82, 0x41, 0x84, 0x21, 0x88, 0x11, 0x90, 0x09, 0xa0, 0x05, 0xc0, 0x03, 0xff, 0xff
                           };
const uint8_t pict2bpp[] = {
  0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
  0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
  0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
  0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
  0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
  0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
  0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
  0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
  0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
  0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
  0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
  0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
  0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
  0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
  0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
  0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
};
const uint8_t pict4bpp[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
  0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
  0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
  0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};



void drawTestScreen() {
  DBGSerial.printf("Use FB: %d ", use_fb); DBGSerial.flush();
  tft.useFrameBuffer(use_fb);
  SetupOrClearClipRectAndOffsets();
  uint32_t start_time = millis();
  tft.fillScreen(use_fb ? ST7735_RED : ST7735_BLACK);
  //tft.setFont(Inconsolata_60);
  tft.setFont(Arial_24);
  tft.setTextColor(ST7735_WHITE);
  tft.setCursor(0, 0);
  tft.println("Test");
  tft.setTextColor(ST7735_WHITE, ST7735_RED);
  tft.println("text");
  tft.setCursor(85, 65);
  tft.print("XYZ");
  tft.setFontAdafruit();
  tft.setTextSize(2);
  tft.setTextColor(ST7735_WHITE);
  tft.println("01234");
  tft.setTextColor(ST7735_WHITE, ST7735_GREEN);
  tft.println("56789!@#$%");

  tft.drawRect(0, 150, 100, 50, ST7735_WHITE);
  tft.drawLine(0, 150, 100, 50, ST7735_GREEN);
  //tft.fillRectVGradient(125, 150, 50, 50, ST7735_GREEN, ST7735_YELLOW);
  //tft.fillRectHGradient(200, 150, 50, 50, ST7735_YELLOW, ST7735_GREEN);
  // Try a read rect and write rect
#ifdef DEBUG_PIN
  digitalWrite(DEBUG_PIN, HIGH);
#endif

  tft.readRect(0, 0, 50, 50, pixel_data);
  // For heck of it lets make sure readPixel and ReadRect 
  // give us same data, maybe check along diagnal?
  for (uint i=0; i < 50; i++) {
    uint16_t pixel_color = tft.readPixel(i,i);
    if (pixel_color != pixel_data[i*50+i]) {
      DBGSerial.printf("Read rect/pixel mismatch: %d %x %x\n", i, pixel_color,pixel_data[i*50+i]);
    }    
  }

#ifdef DEBUG_PIN
  digitalWrite(DEBUG_PIN, LOW);
#endif
  tft.writeRect(250, 0, 50, 50, pixel_data);

  // Lets try to pack this rectangle of data into 8 byte
  tft.readRect(85, 65, 50, 50, pixel_data);
  uint16_t *ppd16 = pixel_data;
  uint8_t *ppd8 = (uint8_t*)pixel_data;
  uint8_t palette_cnt = 0;
  int palette_index;
  for (int i = 0; i < 2500; i++) {
    for (palette_index = 0; palette_index < palette_cnt; palette_index++) {
      if (*ppd16 == palette[palette_index])
        break;
    }
    if (palette_index >= palette_cnt) {
      palette[palette_cnt++] = *ppd16;  // save away the color
    }
    *ppd8++ = palette_index;
    ppd16++;
  }
  //tft.writeRect8BPP(200, 50, 50, 50, (uint8_t*)pixel_data, palette);
  palette[0] = ST7735_CYAN;
  palette[1] = ST7735_OLIVE;
  //tft.writeRect1BPP(75, 100, 16, 16, pict1bpp, palette);
  //tft.writeRect1BPP(320 - 90, 75, 16, 16, pict1bpp, palette);

  palette[2] = ST7735_MAROON;
  palette[3] = ST7735_PINK;
  //tft.writeRect2BPP(75, 125, 32, 16, pict2bpp, palette);

  //tft.writeRectNBPP(15, 125, 32, 16, 2, pict2bpp, palette);
  //tft.writeRectNBPP(75, 150, 16, 16, 4, pict4bpp, palette);

  // Try drawing button
  tft.setFontAdafruit();
  button.drawButton();

  if (use_dma) {
    tft.updateScreenAsync();
  } else {
    tft.updateScreen();
  }
  DBGSerial.println(millis() - start_time, DEC);

  if (use_dma && use_fb) {
    delay(500);
    DBGSerial.printf("DMA error status: %x\n", DMA_ES);
  }

  use_fb = use_fb ? 0 : 1 ;
  DBGSerial.println(use_fb, DEC);


}

void fillScreenTest() {
  tft.useFrameBuffer(0);
  SetupOrClearClipRectAndOffsets();

  tft.fillScreen(ST7735_RED);
  WaitForUserInput();
  tft.fillScreen(ST7735_GREEN);
  WaitForUserInput();
  tft.fillScreen(ST7735_WHITE);
  WaitForUserInput();
  tft.fillScreen(ST7735_BLACK);

}
void printTextSizes(const char *sz) {
  Serial.printf("%s(%d,%d): SPL:%u ", sz, tft.getCursorX(), tft.getCursorY(), tft.strPixelLen(sz));
  int16_t x, y;
  uint16_t w, h;
  tft.getTextBounds(sz, tft.getCursorX(), tft.getCursorY(), &x, &y, &w, &h);
  Serial.printf(" Rect(%d, %d, %u %u)\n", x, y, w, h);  
  tft.drawRect(x, y, w, h, ST7735_GREEN);
}


void drawTextScreen(bool fOpaque) {
  SetupOrClearClipRectAndOffsets();
  tft.setTextSize(1);
  uint32_t start_time = millis();
  tft.useFrameBuffer(use_fb);
  tft.fillScreen(use_fb ? ST7735_RED : ST7735_BLACK);
  tft.setFont(Arial_40);
  if (fOpaque)
    tft.setTextColor(ST7735_WHITE, use_fb ? ST7735_BLACK : ST7735_RED);
  else
    tft.setTextColor(ST7735_WHITE);
  tft.setCursor(0, 5);
  tft.println("AbCdEfGhIj");
  tft.setFont(Arial_28);
  tft.println("0123456789!@#$");
#if 0
  tft.setFont(Arial_20);
  tft.println("abcdefghijklmnopq");
  tft.setFont(Arial_14);
  tft.println("ABCDEFGHIJKLMNOPQRST");
  tft.setFont(Arial_10);
  tft.println("0123456789zyxwvutu");
#endif
  tft.setFont(&FreeMonoBoldOblique12pt7b);
  tft.setCursor(50, tft.getCursorY());
  printTextSizes("AdaFruit");
  tft.println("yAdaFruitq");
    tft.setCursor(50, tft.getCursorY());
  tft.setFont(&FreeSerif12pt7b);
  tft.setTextSize(2);
  printTextSizes("FreeSan12");
  tft.println("FreeSan12q");
  tft.setFont();
    tft.setCursor(50, tft.getCursorY());
  tft.setTextSize(1,2);
  printTextSizes("Sys(1,2)");
  tft.println("Sys(1,2)");
  tft.setTextSize(1);
  printTextSizes("System");
  tft.println("System");
  tft.setTextSize(1);
 

  tft.updateScreen();
  DBGSerial.printf("Use FB: %d OP: %d, DT: %d OR: %d\n", use_fb, fOpaque, use_set_origin, millis() - start_time);
}
//=============================================================================
// Wait for user input
//=============================================================================
void WaitForUserInput() {
  DBGSerial.println("Hit Enter to continue");
  DBGSerial.flush();
  while (DBGSerial.read() == -1) ;
  while (DBGSerial.read() != -1) ;

}

//=============================================================================
// Try continuous update
//=============================================================================
void WaitForFrame(bool fCont, uint32_t wait_frame_count) {
  if (fCont) {
    while (tft.frameCount() < wait_frame_count) yield();
  } else {
    tft.updateScreenAsync();
    WaitForUserInput();
  }
}

void testDMAContUpdate(bool fCont) {
  // Force frame buffer on

  DBGSerial.printf("continuous DMA udpate test - Frame mode on\n"); DBGSerial.flush();
  if (!fCont) {
    DBGSerial.println("Step Mode");
    DBGSerial.flush();
  }
  use_fb = 1; //

  tft.useFrameBuffer(use_fb);
  tft.fillScreen(ST7735_GREEN);

  // check to see if screen memory actually turned green.
  if (use_fb) {
    uint16_t *pw = tft.getFrameBuffer();
    int error_count = 0;
    for (int i = 0; i < (240 * 320); i++)
    {
      if (*pw != ST7735_GREEN) {
        DBGSerial.printf("tft.fillScreen(ST7735_GREEN) not green? %d != %x\n", i, *pw);
        error_count++;
      }
      pw++;
    }
    DBGSerial.printf("tft.fillScreen(ST7735_GREEN(%x)) error count = %d\n", ST7735_GREEN, error_count);
  }

  if (fCont)
    tft.updateScreenAsync(fCont);

  // Start the update
  WaitForFrame(fCont, 10);

  tft.fillScreen(ST7735_YELLOW);
  tft.drawRect(5, 5, 310, 230, ST7735_GREEN);
  tft.fillRect(140, 100, 40, 40, ST7735_BLUE);
  WaitForFrame(fCont, 20);

  tft.fillScreen(ST7735_RED);
  tft.drawRect(5, 5, 310, 230, ST7735_WHITE);

  WaitForFrame(fCont, 30);

  tft.fillScreen(ST7735_BLACK);

  tft.drawRect(5, 5, 310, 230, ST7735_GREEN);
  tft.drawRect(25, 25, 270, 190, ST7735_RED);
  WaitForFrame(fCont, 40);

  digitalWrite(0, HIGH);
  tft.drawRect(5, 5, 310, 230, ST7735_GREEN);
  tft.setCursor(10, 100);
  tft.setTextColor(ST7735_RED, ST7735_BLACK);
  tft.setFont(Arial_20);
  tft.println("DONE");
  tft.setFont();
  tft.setCursor(10, 200);
  tft.setTextColor(ST7735_GREEN);
  tft.print("Done");
  tft.setTextSize(2);
  tft.setCursor(10, 50);
  tft.setTextColor(ST7735_WHITE, ST7735_RED);
  tft.print("Done");
  digitalWrite(0, LOW);
  WaitForFrame(fCont, 45);
  tft.fillRect(0, 0, 2, 2, ST7735_PURPLE);

  if (!fCont) {
    DBGSerial.println("Lets now try doing Continue for a few iterations to see if it changes");
    tft.updateScreenAsync(true);
    while (tft.frameCount() < 10) yield();
  }
  tft.endUpdateAsync();
  DBGSerial.println("after endUpdateAsync");
  tft.waitUpdateAsyncComplete();
  DBGSerial.println("after waitUpdateAsyncComplete");
  DBGSerial.println("Finished test");

  delay(2000);
  DBGSerial.println("Do normal update to see if data is there");
  tft.updateScreen();

}

void loop(void) {
  // See if any text entered
  int ich;
  if ((ich = DBGSerial.read()) != -1) {
    while (DBGSerial.read() != -1) delay(1);

    // See if We have a dma operation in progress?
    if (tft.asyncUpdateActive()) {
      DBGSerial.printf("Async Update active DMA error status: %x\n", DMA_ES);
      //tft.dumpDMASettings();
    }

    if (ich == 'c') {
      use_clip_rect = !use_clip_rect;
      if (use_clip_rect) DBGSerial.println("Clip Rectangle Turned on");
      else DBGSerial.println("Clip Rectangle turned off");
      return;
    }
    if (ich == 'd') {
      use_dma = !use_dma;
      if (use_dma) DBGSerial.println("DMA Turned on");
      else DBGSerial.println("DMA turned off");
      return;
    }

    if (ich == 's') {
      use_set_origin = !use_set_origin;
      if (use_set_origin) DBGSerial.printf("Set origin to %d, %d\n", ORIGIN_TEST_X, ORIGIN_TEST_Y);
      else DBGSerial.println("Clear origin");
      return;
    }

    if (ich == 'o')
      drawTextScreen(1);
    else if (ich == 'f')
      fillScreenTest();
    else if (ich == 't')
      drawTextScreen(0);
    else if (ich == 'r') {
      testDMAContUpdate(true);
      DBGSerial.println("Returned from testDMAContUpdate");
    }
    else if (ich == 'a') {
      testDMAContUpdate(false);
      DBGSerial.println("Returned from testDMAContUpdate");
    }
    else
      drawTestScreen();
  }

}
 
@mjs513 - Sorry I was out having fun. Actually I was out cleaning gutters, only got about half done. I think the house must have grown as I remember I could have done the whole house 10 years ago in same amount of time.

Will try to take a look. I don't have any of those new fancy 320x240 Adafruit displays. May have to order one... But need to see if any distributors have them now... As Adafruit won't ship to our address....

Anyway here is a sketch I modified that I ran on the ST7735 displays. Added 'f' command to turn frame buffer on and off...
View attachment st7735_t3_simpletest_FB-191005a.zip

Note: I think I am actually testing ST7789 240x240 in the sketch

EDIT: Adafruit out of stock, Digikey - 0 available, Mouser does not list...
 
Last edited:
@mjs513 - With your test program, it looks like the issue is from the code explicitly setting frame buffer:
Code:
DMAMEM uint16_t tft_frame_buffer[240 * 320];
...
  tft.setFrameBuffer(tft_frame_buffer);
You comment out that call to set the frame buffer and the program works...
Investigating
 
Back
Top