Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readRect() function not working properly #506

Closed
markradev opened this issue Jan 9, 2024 · 11 comments
Closed

readRect() function not working properly #506

markradev opened this issue Jan 9, 2024 · 11 comments

Comments

@markradev
Copy link

markradev commented Jan 9, 2024

Carefully written Issues are more likely to be given priority.
丁寧に記述された報告は優先して対応される可能性が高くなります。

Environment ( 実行環境 )

  • MCU or Board name: ESP32-S3-DEV-KIT-N8R8
  • Panel Driver IC: ST7789
  • Bus type: SPI
  • LovyanGFX version: v1.1.12
  • FrameWork version: Arduino
  • Build Environment: PlatformIO
  • Operating System: Windows

Problem Description ( 問題の内容 )

readRect() function not working properly under LovyanGFX. However, if you use the tft_eSPI library it works.
I cut out a piece of the bottom left 8 and pasted it back into the top right. The colors are not correct.
I've already tried a lot of different SPI settings and speeds for read and write and different color settings.
The read test also shows some errors, but it is successful under tft_eSPI.

Expected Behavior ( 期待される動作 )

Correct representation of the colors/pixels top right (cut/taken from bottom left) with tft_eSPI
tft_eSPI

Pixel value written = 1
Pixel value read = 1
PASS
Pixel value written = 2
Pixel value read = 2
PASS
Pixel value written = 4
Pixel value read = 4
PASS
Pixel value written = 8
Pixel value read = 8
PASS
Pixel value written = 10
Pixel value read = 10
PASS
Pixel value written = 20
Pixel value read = 20
PASS
Pixel value written = 40
Pixel value read = 40
PASS
Pixel value written = 400
Pixel value read = 400
PASS
Pixel value written = 100
Pixel value read = 100
PASS
Pixel value written = 200
Pixel value read = 200
PASS
Pixel value written = 400
Pixel value read = 400
PASS
Pixel value written = 800
Pixel value read = 800
PASS
Pixel value written = 1000
Pixel value read = 1000
PASS
Pixel value written = 2000
Pixel value read = 2000
PASS
Pixel value written = 4000
Pixel value read = 4000
PASS
Pixel value written = 8000
Pixel value read = 8000
PASS

Actual Behavior ( 実際の動作 )

Wrong colors top right (cut/taken from bottom left) and ERROR output on read example with LovyanGFX
LovyanGFX

Pixel value written = 1
Pixel value read = 0
ERROR ^^^^
Pixel value written = 2
Pixel value read = 0
ERROR ^^^^
Pixel value written = 4
Pixel value read = 0
ERROR ^^^^
Pixel value written = 8
Pixel value read = 40
ERROR ^^^^
Pixel value written = 10
Pixel value read = 80
ERROR ^^^^
Pixel value written = 20
Pixel value read = 100
ERROR ^^^^
Pixel value written = 40
Pixel value read = 200
ERROR ^^^^
Pixel value written = 80
Pixel value read = 400
ERROR ^^^^
Pixel value written = 100
Pixel value read = 0
ERROR ^^^^
Pixel value written = 200
Pixel value read = 0
ERROR ^^^^
Pixel value written = 400
Pixel value read = 0
ERROR ^^^^
Pixel value written = 800
Pixel value read = 800
PASS
Pixel value written = 1000
Pixel value read = 1000
PASS
Pixel value written = 2000
Pixel value read = 2000
PASS
Pixel value written = 4000
Pixel value read = 4000
PASS
Pixel value written = 8000
Pixel value read = 8000
PASS

Steps to reproduce ( 再現のための前提条件 )

Code to reproduce this issue ( 再現させるためのコード )

#include <LovyanGFX.hpp>
//#include <LGFX_TFT_eSPI.hpp>
//#include <LGFX_AUTODETECT.hpp> 
#include "DSEG7_custom.h"
//#include "textFont.h"

class LGFX : public lgfx::LGFX_Device
{

	lgfx::Panel_ST7789    _panel_instance;
	lgfx::Bus_SPI        	_bus_instance;   
	lgfx::Light_PWM     	_light_instance;

  public:

	LGFX(void)
	{
		{ 
			auto cfg = _bus_instance.config();    

			// SPI
			cfg.spi_host = SPI2_HOST;     // VSPI_HOST 
			cfg.spi_mode = 0;             // SPI (0 - 3)
			cfg.freq_write = 80000000;    
			cfg.freq_read  = 7000000;    
			cfg.spi_3wire  = true;        
			cfg.use_lock   = true;        
			cfg.dma_channel = SPI_DMA_CH_AUTO; // DMA(0=DMA / 1=1ch / 2=ch / SPI_DMA_CH_AUTO)

			cfg.pin_sclk = 12;            // SPI SCLK
			cfg.pin_mosi = 11;            // SPI MOSI
			cfg.pin_miso = -1;            // SPI MISO (-1 = disable)
			cfg.pin_dc   =  8;            // SPI D/C

			_bus_instance.config(cfg);    
			_panel_instance.setBus(&_bus_instance);      
		}

		{ 
			auto cfg = _panel_instance.config();    

			cfg.pin_cs           =    10;  // CS
			cfg.pin_rst          =     9;  // RST
			cfg.pin_busy         =    -1;  // BUSY (-1 = disable)

			cfg.panel_width      =   170;   
			cfg.panel_height     =   320;  
			cfg.offset_x         =    35;   
			cfg.offset_y         =     0;  
			cfg.offset_rotation  =     0;  
			//cfg.dummy_read_pixel =     8;  
			//cfg.dummy_read_bits  =     1;  
			cfg.readable         =  true;  
			cfg.invert           =  true;   // Display invert
			cfg.rgb_order        = false;  
			cfg.dlen_16bit       = false;  	// 16bit SPI
			cfg.bus_shared       = false; 	// SD true (drawJpgFile)

			//cfg.memory_width     =   240;  
		       //cfg.memory_height    =   320;  

			_panel_instance.config(cfg);
		}

		{ 
			auto cfg = _light_instance.config();    

			cfg.pin_bl = 17;              
			cfg.invert = false;           
			cfg.freq   = 44100;           
			cfg.pwm_channel = 7;          

			_light_instance.config(cfg);
			_panel_instance.setLight(&_light_instance);  
		}
		setPanel(&_panel_instance); 
  }
};


#define TFT_BL 17            
#define TFT_BACKLIGHT_ON HIGH               

LGFX tft;															
LGFX_Sprite bgSprite(&tft);											
LGFX_Sprite numSprite(&tft);

//static TFT_eSPI tft;               
//static TFT_eSprite bgSprite(&tft);
//static TFT_eSprite numSprite(&tft);

uint16_t bg[900] = {0};

unsigned long previousMillis = 0;                   
const long interval = 10;                         
int counter = 0;                                    
int counterSec = 0;

void TFT_SET_BL(uint8_t Value) {
  if (Value < 0 || Value > 100) {
    log_e("ERROR! Value out of range. Value is set to 50 percent.");
    Value = 50;
    analogWrite(TFT_BL, Value * 2.55);
  } else {
    analogWrite(TFT_BL, Value * 2.55);
  }
}

void setup() {
  Serial.begin(921600);
   
  tft.init(); 
  
  //tft.setColorDepth(16);
  //bgSprite.setColorDepth(16);
  //numSprite.setColorDepth(16);
  
  tft.setRotation(1);                                 
  tft.fillScreen(TFT_BLACK);                                       
  tft.setFreeFont(&DSEG7_Classic_Bold_Italic_44);
  tft.setTextDatum(TR_DATUM);
  
  bgSprite.createSprite(320, 170);                    
  bgSprite.setTextColor(TFT_BLACK, 0x1111);   
  bgSprite.setTextSize(1); 
  bgSprite.fillSprite(0x3333);
  bgSprite.setTextDatum(BL_DATUM);
  bgSprite.setFreeFont(&DSEG7_Classic_Bold_Italic_44);
  bgSprite.drawString("8765432", 10, 151);
  bgSprite.pushSprite(0, 0);

  numSprite.createSprite(152, 65);                    
  numSprite.setTextColor(TFT_BLACK, 0x5555);   
  numSprite.setTextSize(1);                              
  numSprite.fillSprite(0x5555);
  numSprite.setTextDatum(BR_DATUM);
  numSprite.setFreeFont(&DSEG7_Classic_Bold_Italic_44);
  
  delay(300);     	          	  	                
  pinMode(TFT_BL, OUTPUT);
  TFT_SET_BL(30);
  //tft.setBrightness(30);
}

void loop() {
  //log_e("LOOP START");
  unsigned long currentMillis = millis();             
  
  if (currentMillis - previousMillis >= interval) {   
    previousMillis = currentMillis;                  
    counter++;                                      
   
    if(counter>99){
      counter=0; 
      counterSec++; 
      numSprite.drawNumber(counterSec, 70, 55);

      tft.readRect(15, 120, 30, 30, bg);         // <----     
      delay(100);
      tft.pushRect(260, 20, 30, 30, bg);            // <----
      
      delay(1000);
    }
    numSprite.drawNumber(counter, 145, 55);     
    tft.drawNumber(counter, 240, 55);
    numSprite.pushSprite(5, 22);
  }
}
/*

// --------------------Read Test------------------------
// Walking 1 write and read pixel test

//#include <TFT_eSPI.h>
#include <SPI.h>

#define TDELAY 500

//TFT_eSPI tft = TFT_eSPI(170,320); 
static LGFX tft;

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

  tft.init();
  tft.fillScreen(0xF81F);
}

void loop() {
  static uint32_t wr = 1;
  static uint32_t rd = 0xFFFFFFFF;

  delay(TDELAY);

  tft.drawPixel(30,30,wr);
  Serial.print(" Pixel value written = ");Serial.println(wr,HEX);
  
  rd = tft.readPixel(30,30);
                Serial.print(" Pixel value read    = ");Serial.println(rd,HEX);

  if (rd!=wr) {
    Serial.println(" ERROR                 ^^^^");
    //while(1) yield();
  }
  else Serial.println(" PASS ");
  // Walking 1 test
  wr = wr<<1;
  if (wr >= 0x10000) wr = 1;
}
*/
@tobozo
Copy link
Collaborator

tobozo commented Jan 10, 2024

hi,

have you tried readRectRGB() ?

@markradev
Copy link
Author

hi,

have you tried readRectRGB() ?

Thanks. It seems the function cannot be overloaded with readRectRGB() and uint16_t. When I set the array to uint8_t it only briefly shows me a black display and doesn't even draw the section at the top right.

@tobozo
Copy link
Collaborator

tobozo commented Jan 10, 2024

that's because a rgb pixel is composed of 3x uint8_t, so you need to change the data type and the data size in your buffer:

uint8_t * my_buffer = (uint8_t *) malloc( width * height * 3 );

also you'll need to use the relevant method with a hint to the color type:

tft.pushImage( x, y, width, height, (lgfx:: rgb888_t*)my_buffer  );

@markradev
Copy link
Author

that's because a rgb pixel is composed of 3x uint8_t, so you need to change the data type and the data size in your buffer:

uint8_t * my_buffer = (uint8_t *) malloc( width * height * 3 );

also you'll need to use the relevant method with a hint to the color type:

tft.pushImage( x, y, width, height, (lgfx:: rgb888_t*)my_buffer  );

That gives me this result
Screen_3

@tobozo
Copy link
Collaborator

tobozo commented Jan 10, 2024

that's an odd result indeed, looks worse than the first test with the wrong colors. I don't have the exact same display model so I can't verify.

I did some research and found out that TFT_eSPI's ST7789 read frequency is 20MHz, however your setup uses 7MHz, is there any reason this particular value was picked?

    cfg.freq_read  = 7000000;    

sometimes a wrong freq_read value can mess up the colors, which means your initial approach with tft.readRect() may have been right and you should play with cfg.freq_read value while ignoring my previous suggestions to try with tft.readRectRGB()

btw I wonder why you use pinMode and TFT_SET_BL, is there anything broken with tft.setBrightness()?

@markradev
Copy link
Author

markradev commented Jan 10, 2024

that's an odd result indeed, looks worse than the first test with the wrong colors. I don't have the exact same display model so I can't verify.

I did some research and found out that TFT_eSPI's ST7789 read frequency is 20MHz, however your setup uses 7MHz, is there any reason this particular value was picked?

    cfg.freq_read  = 7000000;    

sometimes a wrong freq_read value can mess up the colors, which means your initial approach with tft.readRect() may have been right and you should play with cfg.freq_read value while ignoring my previous suggestions to try with tft.readRectRGB()

btw I wonder why you use pinMode and TFT_SET_BL, is there anything broken with tft.setBrightness()?

I also assume that it has to do with the SPI frequency for read.
I have now tested again with tft_eSPI. For more than 11 MHz, tft_eSPI also shows me the wrong color (red background).
Likewise, from 11 MHz with LovyanGFX, the errors in the read test increase.

7 MHz was the maximum in order not to produce errors with tft_eSPI, which is why I chose that, that was before my display output. With LovyanGFX the errors only increase from 11 MHz. Nothing changes underneath.
Strangely enough, with tft_eSPI, the errors become incorrect with numbers above 800 and with LovyanGFX below 800 errors occur.

I tried all the settings in combination, which unfortunately didn't result in any improvement. Various SPI hosts, speeds (down to 10 kHz and up to 20 MHz) and SPI modes.

It looks like I can't use LovyanGFX for read functions with my display, so I'll have to resort to tft_eSPI or use another method for output, because of limitation of SPI capability.

tft.setBrightness() works, I only used the other lines for tft_eSPI.

@tobozo
Copy link
Collaborator

tobozo commented Jan 11, 2024

It looks like I can't use LovyanGFX for read functions with my display

it's unfair to blame LovyanGFX just because I failed to find the problem in your code

let's do a last test:

  • remove the #include "DSEG7_custom.h" line just to be sure it doesn't interfer with the test
  • use malloc(width * height * 3) or ps_malloc(width * height * 3) to allocate your buffer
  • comment out those lines to see how the driver behaves with the default Bus_SPI settings:
  // cfg.spi_host = SPI2_HOST; 
  // cfg.freq_write = 80000000;    
  // cfg.freq_read  = 7000000;  

@lovyan03
Copy link
Owner

読出し周波数に依存して以下のパラメータを適切に変更する必要があります。
cfg.dummy_read_pixel = 8;
cfg.dummy_read_bits = 1;
すべてのパネルと周波数で安定する設定は存在しません。必要に応じて自分で設定値を見つけてください。

@lovyan03
Copy link
Owner

LovyanGFXが使えないと思うなら、あなたは別のドライバを使えばいいと思います。

@markradev
Copy link
Author

I'm sorry, but there has been a big misunderstanding here. I didn't mean LovyanGFX or even blamed it, but rather my hardware, the display and its SPI capability. LovyanGFX is a great library, otherwise I wouldn't use it.
I also wanted to kindly express that I don't want to bother you any further. Thank you for your time and effort to help.
It's not your fault either.

Unfortunately, your last suggestion didn't bring about any change. That doesn't matter, I'll think of a solution. Thanks again for your time.

I also have to say that I am new to this topic.

cfg.dummy_read_pixel = 8;
cfg.dummy_read_bits = 1;

For these two, I thought it was just for demonstration purposes or examples, so I commented it out. However, the default setting for the ST7789 is still used, which is the following:

cfg.dummy_read_pixel = 16;
cfg.dummy_read_bits = 1;

This was also used in another project with the ST7789. Unfortunately it didn't work for me.
I tested everything from 0 to 82 bits. Unfortunately there was nothing suitable, but the setting with cfg.dummy_read_pixel = 32 came closest; and at 56, it was still wrong. Maybe it's because I'm using the ST7789v3.

As I said, I'll think of another solution and thank you.

@lovyan03
Copy link
Owner

//  static uint32_t wr = 1;  /// ← this is RGB888 value
static uint16_t wr = 1;  /// ← this is RGB565 value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants