TFT_HX8357_Due pushColor after setRotation issue?

My HVGA 480x320 display does not handle pushColor correctly after setRotation.

Is this issue dependent from the hardware, or from the library TFT_HX8357_Due used?

My 2.8" 320x240 with MCUFRIEND_kbv does not show this error.

Links to the displays used:

https://www.aliexpress.com/item/3-2-inch-TFT-LCD-screen-module-Ultra-HD-320X480-for-Arduino-MEGA-2560-R3-Board/32604352555.html

Code showing the issue on my displays:

// PushColorSetRotationIssue.ino

// select one
#include <TFT_HX8357_Due.h>
//#include <MCUFRIEND_kbv.h> // works ok on my display

#ifdef _TFT_HX8357_DueH_
TFT_HX8357_Due TargetDisplay;
#define USE_TEXTSIZE 2
#endif

#ifdef MCUFRIEND_KBV_H_
MCUFRIEND_kbv TargetDisplay;
#define USE_TEXTSIZE 1
#endif


void setup()
{
  TargetDisplay.begin(); // more common than init()
  TargetDisplay.fillScreen(0);
  TargetDisplay.drawRect(0, 0, TargetDisplay.width() - 1, TargetDisplay.height() - 1, 0x001F);
  TargetDisplay.setTextSize(USE_TEXTSIZE);
  TargetDisplay.setTextColor(0xF800);
}

void loop()
{
  reportTestCase("this shows the issue");
  for (uint8_t target_r = 0; target_r < 4; target_r++)
  {
    TargetDisplay.fillScreen(0x7BE0);
    TargetDisplay.setRotation(target_r);
    TargetDisplay.setCursor(0, 0);
    showTestPattern();
    delay(3000);
    reportRotation();
    delay(5000);
  }
  reportTestCase("fillScreen after setRotation");
  for (uint8_t target_r = 0; target_r < 4; target_r++)
  {
    TargetDisplay.fillScreen(0x7BE0);
    TargetDisplay.setRotation(target_r);
    TargetDisplay.fillScreen(0x7BE0);
    delay(1000);
    TargetDisplay.setCursor(0, 0);
    showTestPattern();
    delay(3000);
    reportRotation();
    delay(5000);
  }
  reportTestCase("setCursor after setRotation");
  for (uint8_t target_r = 0; target_r < 4; target_r++)
  {
    TargetDisplay.fillScreen(0x7BE0);
    TargetDisplay.setCursor(0, 0);
    TargetDisplay.setRotation(target_r);
    TargetDisplay.setCursor(TargetDisplay.width() - 1,  TargetDisplay.height() - 1);
    showTestPattern();
    delay(3000);
    reportRotation();
    delay(5000);
  }
}

void reportTestCase(const char* message)
{
  TargetDisplay.fillScreen(0x001F);
  TargetDisplay.setCursor(0,  TargetDisplay.height() / 2);
  TargetDisplay.print(message);
  delay(2000);
}

void showTestPattern()
{
  uint32_t _width = TargetDisplay.width();
  uint32_t _height =  TargetDisplay.height();
#ifdef _TFT_HX8357_DueH_
  TargetDisplay.setWindow(0, 0, _width, _height);
#endif
#ifdef MCUFRIEND_KBV_H_
  TargetDisplay.setAddrWindow(0, 0, _width, _height);
  bool first = true;
#endif
  for (uint32_t i = 0; i < _width * _height; i++)
  {
#ifdef _TFT_HX8357_DueH_
    TargetDisplay.pushColor((i < _width * _height / 4) ? 0xFFFF : 0xFD20);
#endif
#ifdef MCUFRIEND_KBV_H_
    uint16_t color = (i < _width * _height / 4) ? 0xFFFF : 0xFD20;
    TargetDisplay.pushColors(&color, 1, first);
    first = false;
#endif
  }
}

void reportRotation()
{
  TargetDisplay.setCursor(0, 0);
  //  TargetDisplay.println();
  TargetDisplay.print("Target Rotation is ");
  TargetDisplay.println(TargetDisplay.getRotation());
  TargetDisplay.println("should be white 1/4, then orange");
}

The workaround with fillScreen() produces flicker, which I try to avoid.

Is this issue only on my display? Is there some other workaround?

Thank you for any help or suggestion.

Surely you would setRotation() before fillScreen()
Otherwise you would be plotting pixels to the wrong area of GRAM.

Both libraries will fill the screen pretty fast. Often before the next hardware refresh of the Raster Scan.

Yes, when you change the geometry with setRotation(), you can often see a mirrored or reflected image because the scan directions are changed. (at least in MCUFRIEND_kbv)

In practice, you choose an Aspect at the setup() of a sketch. And always draw in the same directions in loop()

I still do not know what you are trying to achieve. Some screenshots or a simple explanation would be helpful.

David.

david_prentice:
Surely you would setRotation() before fillScreen()
Otherwise you would be plotting pixels to the wrong area of GRAM.

Both libraries will fill the screen pretty fast. Often before the next hardware refresh of the Raster Scan.

Yes, when you change the geometry with setRotation(), you can often see a mirrored or reflected image because the scan directions are changed. (at least in MCUFRIEND_kbv)

In practice, you choose an Aspect at the setup() of a sketch. And always draw in the same directions in loop()

I still do not know what you are trying to achieve. Some screenshots or a simple explanation would be helpful.

David.

Thank you for the quick answer.

I try to explain shortly:

The sole purpose of the code that I posted, is to show the issue.

With my display and TFT_HX8357_Due the output is incorrect if NO clearScreen is called after setRotation.

My Buffered_GFX template class uses pushColor for updateToTarget for TFT_HX8357_Due. If the TargetDisplay is rotated after creation of the Buffered_GFX instance, the error shows up.

related to:
http://forum.arduino.cc/index.php?topic=305945.msg3025446#msg3025446
http://forum.arduino.cc/index.php?topic=305945.msg3025432#msg3025432http://forum.arduino.cc/index.php?topic=437623.msg3017927%23msg3017927

I still do not understand.

If you have a lot of text on a Portrait screen, you can use VertScroll() to move previously written text.
And you only need to draw the fresh text line. This is incredibly fast.

Even if you redraw a whole screenful of text, the hardware can assist. e.g. when drawing text with its own background.

If you have complex monochrome shapes, you can store these in a realistic amount of SRAM e.g. 8 pixels to a byte.

Most Arduinos are short of SRAM e.g. Uno. It is easier to re-compute and draw a graphic image.

David.

david_prentice:
I still do not understand.

If you have a lot of text on a Portrait screen, you can use VertScroll() to move previously written text.
And you only need to draw the fresh text line. This is incredibly fast.

Even if you redraw a whole screenful of text, the hardware can assist. e.g. when drawing text with its own background.

If you have complex monochrome shapes, you can store these in a realistic amount of SRAM e.g. 8 pixels to a byte.

Most Arduinos are short of SRAM e.g. Uno. It is easier to re-compute and draw a graphic image.

David.

quote from Adafruit_GFX.cpp

    // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
    // THIS IS ON PURPOSE AND BY DESIGN.  The background color feature
    // has typically been used with the 'classic' font to overwrite old
    // screen contents with new data.  This ONLY works because the
    // characters are a uniform size; it's not a sensible thing to do with
    // proportionally-spaced fonts with glyphs of varying sizes (and that
    // may overlap).  To replace previously-drawn text when using a custom
    // font, use the getTextBounds() function to determine the smallest
    // rectangle encompassing a string, erase the area with fillRect(),
    // then draw new text.  This WILL infortunately 'blink' the text, but
    // is unavoidable.  Drawing 'background' pixels will NOT fix this,
    // only creates a new set of problems.  Have an idea to work around
    // this (a canvas object type for MCUs that can afford the RAM and
    // displays supporting setAddrWindow() and pushColors()), but haven't
    // implemented this yet.

Solved!

I looked at fillScreen to find the side-effect that makes it work.

fillRect calls setAddrWindow with the correct parameter values.

It often happens to me to confound edge values with width and height.

Lesson learned, hope others may learn from it also, sorry for the noise produced.

I leave the test code as it is, as an exercise for whoever would like to try it. Its worth the trial, to see the other issue (that is of no importance for me, as I use Adafruit_GFX for text output).

Looking at the original sketch posted I see a subtle error.

The setWindow() function sets a bounding box in pixel coordinates not in terms of width and height.
To get you sketch to work correctly use:

  TargetDisplay.setWindow(0, 0, _width-1, _height-1);

in the showTestPattern() function.

I tried the suggestion in post #8 and it works fine.

Note that the TFT_HX8357_Due library will render the Adafruit free fonts (example All_Free_Fonts_Demo) and also with background (example Free_Font_Demo). With the improved rendering algorithm employed and faster speed this is almost blink free.

The library has additional features like being able to set the text datum, for example to right justify or center text on a coordinate. See Free_Font_Demo example. Also there is a padding feature which helps automatically overwrites long numbers with short ones by defining the padding width.

Thank you very much for your answer. I like and appreciate your work!

The version of TFT_HX8357_Due installed is 0.26.0. The driver selected is HX8357B.

If I change the text color to black, I see the other effect more clearly on my display:

Rotation 0: text shows reversed in the white field
Rotation 1: correct on white
Rotation 2: reversed and on orage
Rotation 3: correct, but on orange

Is this my display? is there an other error in my sketch? or is it the use of the default font?

kind regards

Jean-Marc Zingg

all correct with #define ILI9481

I need to look for the reason I changed that, I used #define ILI9481 on MEGA.

I need to search in my posts, I think I had an issue that was solved by #define HX8357B.

Sorry, more noise from me. Got confused. Struggling with template classes, not my usual work.