vindar / ILI9341_T4

Optimized ILI9341 screen driver library for Teensy 4/4.1, with vsync and diff. updates.
GNU Lesser General Public License v2.1
70 stars 12 forks source link

[bug] Long update delays when few changes #8

Closed ReinBentdal closed 2 years ago

ReinBentdal commented 2 years ago

I have tested the library printing the FPS in the corner of the screen to check performance. And the UI is super snappy.

But I removed the FPS counter and the ui suddenly became much more unresponsive with clear delay between user input and changes in UI. It seems like the first frame after a change is instant, but the preceding ones are not. The FPS counter caused continuous changes in the UI, but disabling it results in only UI changes in the case of user input.

I am using double buffering and differential updates (both 1 and 2 diff buffers). Disabling the diff buffers and the ui is again snappy. There thus seem to be a problem with the diff buffers in the case of, in general no changes, but then sudden changes in UI cause lag.

If you are unable to reproduce or want more context, I can try to make a demo.

vindar commented 2 years ago

Hi,

Which v_sync spacing are you using ? With tft.setVsyncSpacing(-1), the driver can drop frames which may look like the UI is lagging. However, if you are using a number >= 0, then there is indeed something wrong... I cannot really do anything if I am not able to reproduce the bug. Could you provide a demo ? Then I will happily look into it :-)

ReinBentdal commented 2 years ago

I think this example appropriately reproduces my issue. In my case, the UI usually "freezes" at 900ms before continuing, where it should jump to 1000ms after 100ms. Would guess it has something to do with the diff gap.

I think the code is self explanatory, io_update is just a dummy user input function

#include <ILI9341_T4.h>
#include <tgx.h>

#include<font_tgx_OpenSans.h>
#include <Print.h>
#include <elapsedMillis.h>

constexpr uint8_t CS_PIN = 25;
constexpr uint8_t RST_PIN = 14;
constexpr uint8_t DC_PIN = 37;
constexpr uint8_t MOSI_PIN = 11;
constexpr uint8_t MISO_PIN = 12;
constexpr uint8_t SCK_PIN = 13;

ILI9341_T4::ILI9341Driver tft( CS_PIN, DC_PIN, SCK_PIN, MOSI_PIN, MISO_PIN, RST_PIN); 

DMAMEM uint16_t fb[240*320];
DMAMEM uint16_t ib[240*320];

ILI9341_T4::DiffBuffStatic<4096> diff1;
ILI9341_T4::DiffBuffStatic<4096> diff2;

tgx::Image<tgx::RGB565> im(fb, 320, 240);

#define SPI_SPEED       50000000

void setup(void) {
    while (!tft.begin(SPI_SPEED, SPI_SPEED)) delay(1000);

    tft.setScroll(0);
    tft.setRotation(3);
    tft.setFramebuffers(ib);
    tft.setDiffBuffers(&diff1);
    tft.setDiffGap(4);
    tft.setRefreshRate(120);
    tft.setVSyncSpacing(2);

    im.fillScreen(tgx::RGB565_Black);
}

int inc;
bool new_inc = false;
String last_time;
elapsedMillis time;

void io_update() {
  if (time > 2000) {
    time = 0;
    inc = 0;
    new_inc = true;
  } else if (time > 1800 && inc == 4) {
    inc = 5;
    new_inc = true;
  } else if (time > 1700 && inc == 3) {
    inc = 4;
    new_inc = true;
  } else if (time > 1100 && inc == 2) {
    inc = 3;
    new_inc = true;
  } else if (time > 1000 && inc == 1) {
    inc = 2;
    new_inc = true;
  } else if (time > 900 && inc == 0) {
    inc = 1;
    new_inc = true;
  }
}

char* str[6] = {"0 0ms", "1 900ms", "2 1000ms", "3 1100ms", "4 1700ms", "5 1800ms"};

void draw() {
  im.fillScreen(tgx::RGB565_Black);

  for (int i = 0; i < 6; i++) {
    im.drawText(str[i], tgx::iVec2{10, (i+1)*15}, i == inc ? tgx::RGB565_Red : tgx::RGB565_Green, font_tgx_OpenSans_16, false);
  }

  if (new_inc) {
    new_inc = false;
    last_time = "current: ";
    last_time += time;
    last_time += "ms";
  }

  im.drawText(last_time.c_str(), tgx::iVec2{150, 15}, tgx::RGB565_Red, font_tgx_OpenSans_16, false);

  tft.update(fb, false);
}

void loop() {

  io_update();

  if (!tft.asyncUpdateActive()) {
    draw();
  }
}
ReinBentdal commented 2 years ago

again, disabling the diff buffers and the update sequence is as expected (remove setDiffBuffers, setDiffGap).

vindar commented 2 years ago

Ok, just tried the code and indeed I can reproduce the bug... I will investigate right away !

vindar commented 2 years ago

I think I got it. It was a stupid mistake in the computation of the starting time of the next frame to draw...

I just pushed a tentative fix. Can you try it and tell me if it works for you too ?

ReinBentdal commented 2 years ago

I will see if I can test it out later today 👍

ReinBentdal commented 2 years ago

My initial problem is now gone and it looks like your fix fixed the issue!