Is it possible to create a screen driver like this one https://github.com/vindar/ILI9341_T4 but for a ST7789 screen like this one https://www.waveshare.com/wiki/1.9inch_LCD_Module. If so how should i go about it?
#define USE_ST7789
// This example runs on teensy 4.0/4.1 with ILI9341 via SPI.
// the screen driver library : https://github.com/vindar/ILI9341_T4
//#include <ILI9341_T4.h>
#ifdef USE_ST7789
#include <ST7735_t3.h> // Hardware-specific library
#include <ST7789_t3.h> // Hardware-specific library
#else
#include <ILI9341_t3n.h>
#endif
#ifdef USE_ST7789
ST7789_t3 tft = ST7789_t3(TFT_CS, TFT_DC, TFT_RST);
#else
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);
#endif
#ifdef USE_ST7789
tft.init(240, 320); // Init ST7789 320x240
#else
tft.begin(SPI_SPEED);
#endif
void update_display(bool force_whole_display) {
if (!force_whole_display) {
// look for bounding range of changes.
uint16_t first_changed_x = tft.width();
uint16_t last_changed_x = 0;
uint16_t first_changed_y = tft.height();
uint16_t last_changed_y = 0;
for (uint16_t y = 0; y < tft.height(); y++) {
uint16_t* ptftfb_y = &ib[y * tft.width()];
uint16_t* pimage_newfb_y = &fb[y * tft.width()];
uint16_t x;
for (x = 0; x < tft.width(); x++) {
// find first if any change in line.
if (ptftfb_y[x] != pimage_newfb_y[x]) {
if (first_changed_y == tft.height()) first_changed_y = y;
last_changed_y = y;
if (x < first_changed_x) first_changed_x = x;
break;
}
}
// find last change in line
if (x < tft.width()) {
for (x = tft.width() - 1; x > last_changed_x; x--) {
if (ptftfb_y[x] != pimage_newfb_y[x]) {
last_changed_x = x; //
break;
}
}
}
}
// now have the bounds
tft.setClipRect(first_changed_x, first_changed_y, (last_changed_x - first_changed_x) + 1, (last_changed_y - first_changed_y) + 1);
static uint8_t debug_count = 20;
if (debug_count) {
Serial.printf("(%u, %u), (%u, %u)\n", first_changed_x, last_changed_x, first_changed_y, last_changed_y );
debug_count--;
}
} else {
tft.setClipRect();
}
memcpy(ib, fb, sizeof(fb));
tft.updateScreen(); // simply update.
}
void update_display(bool force_whole_display) {
if (force_whole_display) {
tft.setClipRect();
tft.updateScreen();
return;
}
// lets try writeRect
tft.writeRect(0, 0, tft.width(), tft.height(), fb);
tft.updateChangedAreasOnly(true); // really only need to call this once.
tft.updateScreen(); // simply update.
}
Quick update on some of this stuff.
Yesterday I did some updates to my ili9341_t3n library as well as the ST7735_t3 (includes st7789), for some of this stuff.
the ILI9341_t3n library had some code we were trying out awhile back to have it compute a bounding rectangle what area of the frame buffer is dirty (changed) and if option is set, then updateScreen will only update that area.
I fixed a bug in this code, plus:
update writeRect that in frame buffer mode, it used to say the whole rectangle was updated. This code now checks if a pixel color changes and the dirty region now is the rectangle that bounds all of these changed pixels, unioned with previous dirty region.
This appears to be working with the example sketch (so far only updated the Anti aliased clock sketch. With this the code I used to update the screen from what the graphics library fb was changed from:
Code:void update_display(bool force_whole_display) { if (!force_whole_display) { // look for bounding range of changes. uint16_t first_changed_x = tft.width(); uint16_t last_changed_x = 0; uint16_t first_changed_y = tft.height(); uint16_t last_changed_y = 0; for (uint16_t y = 0; y < tft.height(); y++) { uint16_t* ptftfb_y = &ib[y * tft.width()]; uint16_t* pimage_newfb_y = &fb[y * tft.width()]; uint16_t x; for (x = 0; x < tft.width(); x++) { // find first if any change in line. if (ptftfb_y[x] != pimage_newfb_y[x]) { if (first_changed_y == tft.height()) first_changed_y = y; last_changed_y = y; if (x < first_changed_x) first_changed_x = x; break; } } // find last change in line if (x < tft.width()) { for (x = tft.width() - 1; x > last_changed_x; x--) { if (ptftfb_y[x] != pimage_newfb_y[x]) { last_changed_x = x; // break; } } } } // now have the bounds tft.setClipRect(first_changed_x, first_changed_y, (last_changed_x - first_changed_x) + 1, (last_changed_y - first_changed_y) + 1); static uint8_t debug_count = 20; if (debug_count) { Serial.printf("(%u, %u), (%u, %u)\n", first_changed_x, last_changed_x, first_changed_y, last_changed_y ); debug_count--; } } else { tft.setClipRect(); } memcpy(ib, fb, sizeof(fb)); tft.updateScreen(); // simply update. }
To simply
And this code simplified farther as I really don't need the force whole display stuff.Code:void update_display(bool force_whole_display) { if (force_whole_display) { tft.setClipRect(); tft.updateScreen(); return; } // lets try writeRect tft.writeRect(0, 0, tft.width(), tft.height(), fb); tft.updateChangedAreasOnly(true); // really only need to call this once. tft.updateScreen(); // simply update. }
I then merged these dirty region changes into the ST77xx code and verified that the updates were only drawing sub-region of the clock.
There are still changes I will do over time, like I believe a few graphic primitives don't currently update this dirty region computation.
Plus I could update more of these type primitives to not marked the whole rectangle but only the dirty regions.
But first I will probably merge this dirty region stuff into ILI9488 code and will probably change the test code to at first maybe leave the TGX frame buffer at 320x240 as the example code I believe depends on this to look right. And then will have the writeRect, center it on the display
More playing
Thanks @mjs513
I just updated the ILI9488_t3 library to have the changed area code like ILI9341_t3n
Which is up in this fork/branch: https://github.com/kurte/ILI9488_t3/tree/merge_changed_rect
I updated the one example sketch like I mentioned and included it here.
....
I tried using st7735_t3 with this https://github.com/vindar/tgx using a framebuffer but if i rotate the screen everything gets scrambled on the screen and it also updates the whole screen and not only the parts that change.
Probably.Bolimpa, were you able to get the 1.9" 170x320 screen working? I also have it. It works with the Adafruit library but not with the Teensy ST7735/ST7789.
Kurt, would you happen to know what I would need to modify to get the 170x320 resolution working?