Closed nikthefix closed 3 months ago
@diegomacario @davidos81
BTW, I've just been reviewing this whole comment section and I need to eat some humble pie. I didn't see the tearing so I assumed it was something else. I wasn't looking closely enough. So....many of my comments were useless at best, dismissive at worst. My bad.
nik
@nikthefix thanks for the effort in the provided .zip file!
It seems the update is promising , I did try it , not quite there yet - still a bit slow , but a fantastic effort anyways! We cant wait for the next update!!
But you didn't see any tearing? If so then the next step should just be arithmetic.
nik
@nikthefix absolutely true , no tearing seen!
being honest , this is next level stuff for me , KUDOS to your efforts @nikthefix
@davidos81
Oh I assure you it's not next level. It's just a matter of trawling the datasheets to find all the caveats. But it's interesting because since you 'tuned me in' to seeing the effect I've gone back over some of my old display dev boards and found that most exhibit the same problem with the popular libraries.
Feedback from the display would seem of paramount importance and yet none of the most used libs implement anything like that. And many displays don't have TE broken out.
With RGB displays you're clearly responsible for all timings so it's a different thing entirely. Anyway, I'll get back to it and report.
Thanks for the feedback. Should have something for you in the next couple of days.
nik
@nikthefix I think most cheap board manufacturers from china simply want to get a board out with the lowest common denominator drivers - the stuff you are doing really is the job of ttgo / makerfabs etc.. The hardware is great but support is terrible...
@davidos81 Well I suppose such hardware optimizations are in the domain of the manufacturers whose products utilizes these displays. Yes 'one size fits all' drivers hold us back yet propel us at the same time.
There are 'hidden secrets' not shown in the open datasheets which allow for much greater configuration - if you're a manufacturer. Notice the 'PAGE' attribute in the init codes. Even Liligo (it seems) don't have access to this info - and I did ask. I know this to be true as I stumbled upon them - but didn't know what I was doing with no supporting documentation.
But that doesn't mean we can't have a go.
Lilygo et al do a great job of getting it out there. It's up to us to delve deeper.
nik
@nikthefix Very true!
@davidos81 But I think the maker scene has reached the point where 'hobby level' performance is no longer acceptable. We want our gadgets to perform like iPhones.
We'll get there.
nik
certainly with this display 60fps is easily achievable ..
And retina resolution.
@davidos81 Have you tried the Liliygo T4 amoled yet? It's wonderful.
@nikthefix I really want to , but I could not see a TE line on the schematic , for my purposes , I need 100% tear free updates , do you have it and whats the screen refresh / tearing situation on it ?
Good question. I've been using it with LVGL and haven't noticed any tearing. I will subject it to our tests. I suspect I will be similarly disappointed with the findings.
Edit: Yeah TE not exposed so we could be flogging a dead horse with that one. Big shame.
I looked up the actual LCD from the company you mentioned in earlier posts. I did not see TE line on that , I suspect it would be the same here... sometimes it can be difficult to see tearing...
It's there on the FPC but Lilygo didn't wire it up. Bummer. There will come a time when you'll have to make your own boards.
my bad , I knew it was one or the other , which is why I didnt bother with it further!
Well it's good feedback for Lilygo - expose all the useful pins. Let's hope they read this.
But it's possible that the T4 performs in a different way when put to the test. I'll try it and get back.
I just tested the new driver code and I can confirm I don't see tearing on my T-Display S3 AMOLED either! The colors are slowly updated top-to-bottom instead.
I did a diff between the old driver code and the new one to understand the changes. It's very cool seeing how you can read the spec sheet and implement it. I have no clue had to do that. Thanks so much for the effort @nikthefix!
@nikthefix EXACTLY!!
I forgot to add for the t4 display , the library looks over bloated (to me anyway) compared to the simplicity of this display - just 2 files and a .ino
I have been following this post. I can't do anything about tearing, I can only follow you, but @nikthefix mentioned that the hardware does not connect TE. I can clarify this point. TE has indeed been connected to the GPIO9 Pin of esp32s3.
Regarding the initialization screen parameters, the screen supplier cannot provide us with more information and will only send us a data sheet, so what we currently do is just light up the screen.
@lewisxhe Are you referring to the t4 AMOLED display ?
@lewisxhe Thanks , I will have a look at it again
On 23 Feb 2024, at 13:56, nikthefix @.> @. Ah so were you hoping to use SPIFFS / littleFS / FatFS to store your Gifs? Yeah the new IDE won't play ball for upload at present. But it's a good thing really. Converting your file to a byte array and including it in the sketch is so much more efficient. But for experimentation having a file system is convenient. Especially for web pages etc. You could upload using the espressif flash tools or try implementing your board as a USB Mass Storage Device. But I'd stick with the .h file. Harder work but better in the end. Well, I didn’t respond to this one right off - not sure if it’s something that should be in its own thread or something. But yes, I find the whole .h conversion business to be really time-consuming and cumbersome. I typically find myself in situations where the code on the device stays the same, and I’m simply iterating repeatedly on the uploaded GIF image to see what works visually. Reducing the number of steps to close the feedback loop is ideal!Ideally I just want to drop a file into a folder on my development computer, click a button, and have the file synced. And the board isn’t designed to operate as a USB mass storage class device, I don’t think. That would be perfect also! "The LVGL stuff never worked for me". Can you expand on this? Well, I basically wasn’t able to get an animated GIF, converted to .h, to load and play using LVGL at all. The only way I could get a GIF to play was to use the moononournation Arduino_GFX code. Here’s my writeup on what I got working: https://sites.google.com/site/3dsfinfo/lights-for-model-makers-technology-and-techniques/high-rez-microcontroller-displays It’s a shame that nobody seems to support animated PNG. I only use animated GIF because it’s just adequate for my needs, and because video playback isn’t an option. But GIF has the constrained colour palette, which sucks, especially on a screen as nice as the AMOLED displays. Using PNG or a video would be so much better. :) - NK GuyMessage ID: @.***>
@3Dsf-info The esp32-s3 CAN be set up as a usb mass storage device. There are examples in the Arduino_Esp32 examples section. Another way to do it is to use the Adafruit TinyUSB library - even more MSD examples there.
Alternatively you could use an SD card breakout to quickly install data files (maybe copy them over to internal flash for speed).
Transferring files into the files system could also be done by adding a web interface to the sketch or even ftp.
Lastly, you could always keep a portable old version Arduino IDE to use just as the upload tool. Important to make sure it's portable so it doesn't interfere with your IDE2.x installation - some users have reported issues / conflicts etc.
For video playback with more flexibility than Gif, you might checkout this miniTV project: https://www.youtube.com/watch?v=2NLblyCvJBU&t=7s It's a whole series (appropriately enough) and it's fab!
Also, Arduino_GFX has an example for Mjpeg playback which works well.
nik
@nikthefix @lewisxhe mentions above that the t4 amoled does indeed have a TE connnected to GPIO 9 , can you please do some tests to confirm if that is true ? Cheers in advance!
@davidos81 According to the latest schematic: (https://github.com/Xinyuan-LilyGO/LilyGo-AMOLED-Series/blob/master/schematic/T4-S3-AMOLED.pdf)
...and the lilygo pin defines:
// LILYGO 2.41 Inch AMOLED(RM690B0) S3R8 // https://www.lilygo.cc/products/t4-s3 static const DisplayConfigure_t RM690B0_AMOLED = { 14,//BOARD_DISP_DATA0, 10,//BOARD_DISP_DATA1, 16,//BOARD_DISP_DATA2, 12,//BOARD_DISP_DATA3, 15,//BOARD_DISP_SCK, 11,//BOARD_DISP_CS, BOARD_NONE_PIN,//DC 13,//BOARD_DISP_RESET, -1, //BOARD_DISP_TE, <<<<<<<<<<<<<<<<<<<<<<<<<<<< 8, //command bit 24,//address bit 36000000, (lcd_cmd_t *)rm690b0_cmd, RM690B0_INIT_SEQUENCE_LENGHT, RM690B0_WIDTH,//width RM690B0_HEIGHT,//height 0//frameBufferSize };
... TE is not connected to a GPIO.
GPIO pin 9 for the T4 is shown in schematic and code to be assigned to the display power management ic AVDD_enable pin:
// T-Display AMOLED 2.41 Inch // https://www.lilygo.cc/ static const BoardsConfigure_t BOARD_AMOLED_241 = { RM690B0_AMOLED, &AMOLED_241_TOUCH_PINS, //Touch CS226SE &AMOLED_241_PMU_PINS, //PMU NULL, //SENSOR &AMOLED_241_SD_PINS,//SDCard AMOLED_241_BUTTONTS, //Button Pins 1, //Button Number -1, // pixelsPins -1, //adcPins 9, //PMICEnPins <<<<<<<<<<<<<<<<<<<<<<<<<<<<< false,//framebuffer };
nik
Edit: Just tested with the real board and can confirm the above.
@lewisxhe
Do you have an estimated time until we can purchase the T4 shell / case? I can't wait to get my hands on this.
And also the T-Encoder-Pro?
Many thanks.
T4S3? no connection ? Sorry, I might have remembered it wrong, then I might suggest re-iterating the T4S3 to a version with the TE connected to the GPIO
The 3D files of T4S3 are already on github https://github.com/Xinyuan-LilyGO/LilyGo-AMOLED-Series/blob/master/shell/T4-S3-AMOLED.zip , if you are referring to the store, I am not sure when it will be available for sale. I will inquire on Monday, it should be available for sale soon
3.T-Encoder-Pro should be sold soon
@lewisxhe
Thank you for the information.
Yes I think having the TE to GPIO on T4S3 would be very useful. Even tho most people probably won't need it, it's very good to have it for educational purposes and experimentation.
I will download the T4S3 shell now.
nik
@nikthefix Thanks for looking into that for me , I knew @lewisxhe got confused somewhere!
@lewisxhe @davidos81 @diegomacario
Progress:
I think we're almost there. Please test the attached sketch and feed back.
nik
@lewisxhe @davidos81 @diegomacario
My thinking:
I tried very hard to squeeze the frame data into the blanking periods of the display refresh but there just wasn't enough time at 80MHz. The frame rate would remain unacceptably low even if the frame data were fragmented and transmitted only during these phases. I used the H-Sync phases too but it wasn't enough.
Since we're writing in landscape and the display is refreshing in portrait there is no way to avoid an intersection / collision / strobe causing diagonal artifacts.
So in this test I've used an additional buffer for a matrix rotation (just like the one used in the code for the Lilygo T-Track). Now the refresh scan is the same as the update vector. Combined with a sync from the TE pin we can have clean frames I hope.
I've not yet measured the full screen frame rate but there is room for optimization. Also, I've not yet integrated this mod to work with the lcd_rotate function so for the time being lcd_rotate should not be used. This is a purely landscape experiment.
nik
@nikthefix Absolutley great work !!
The sketch worked perfectly , AWESOME!
So I was right about the screen refreshing in portrait mode after all - at least I am good for something !!
From a technical perspective , I didnt think of this approach - so very clever @nikthefix
If I really had to criticise this approach it would be that you are now doing a massive pixel copy operation (536x240)*2 , but this should be fine for the most tasks!
I think you have almost nailed it @nikthefix
@davidos81 Yes the screen refreshing in portrait mode independently of the logical landscape write to the gram seems absurd but I guess the two components are joined in an immutable hardware way. Indeed you were right and you saw it long before I did.. I just wish that more displays were native landscape.
The pixel copy is no great penalty at 240Mhz cpu / 80Mhz spi and I suggest we have a separate function to push pixels in this fashion only when necessary. Push_colors_tear_safe() for example. We could also do the matrix rotate buffer copy one line at a time if that's more comfortable. It works just as well but is slightly more complicated code.
But this test also paints the worst case scenario - solid horizontal colour blocks. I plan to evolve it to differential update (something I have already working for LVGL on the T4 and the Long) which will reduce display write times and any buffer copy requirements dramatically. This is something that's easy to do in LVGL as it has a built in 'rounder' function which automatically quantizes update regions to fit the even / odd +1 etc requirements of fussy displays.
I'll carry on working on it tomorrow.
nik
@3Dsf-info
I found this which may help with your file system upload in IDE 2.x issue:
@lewisxhe @davidos81 @diegomacario
Progress:
Code cleanup - the files are much smaller now so it's easier to see what's going on. FPS serial monitor. 270 degree rotate 'tear free' option.
Todo:
Add 180 degree portrait tear free option. Add x/y mirroring tear free option for all modes. Fully comment the code. Integrate all rotate options (fast or tear free) into a single function call. Optimize the tear free frame rate. Currently 'tear free' = 20-25fps, non 'tear free' = 50fps (approx).
Todo additional:
Differential updates to the display GRAM using constraint compliant region updates.
Comments:
I've found that the normal non 'tear free' rotate options are absolutely fine for most scenarios - I can't see tearing at all with my usual animations / gifs etc. But block colours can reveal tearing. So maybe we can selectively call the tear free options for critical draws only. The rotate options can be changed at any time so you don't have to commit to just one in Setup().
nik
@nikthefix great work mate !
I think you have gone well out of you way on this one! Am hoping the people here appreciate it
Hi @nikthefix! This morning I finally sat down to continue with my ray-tracer project using your new driver code. The menu I showed here works beautifully now with no tearing at all! I'm using the lcd_PushColors_Rotated_90
function there.
For the part of the program that draws the rendered image to the screen I tried switching to the old but faster version (lcd_PushColors
). I never saw tearing there, so I figured it would be good to just keep using the faster function.
To make those calls work I call lcd_setRotation(1)
before executing them. The curious thing is that things work beautifully with fullscreen updates, but not with partial ones. With partial updates I see lots of artifacts. This minimal code reproduces the bug:
#include "rm67162.h"
#include <TFT_eSPI.h>
#include "hugeFatFont.h"
#define TE_pin 9
#define display_enable_pin 38
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite img = TFT_eSprite(&tft);
TFT_eSprite img2 = TFT_eSprite(&tft);
void IRAM_ATTR ISR();
void setup() {
pinMode(display_enable_pin, OUTPUT);
digitalWrite(display_enable_pin, HIGH);
pinMode(TE_pin, INPUT);
Serial.begin(115000);
img.createSprite(536, 240);
img2.createSprite(200, 100);
rm67162_init();
attachInterrupt(TE_pin, ISR, RISING);
img.loadFont(hugeFatFont);
img2.loadFont(hugeFatFont);
}
void loop() {
// 90 degree rotate - Fullscreen - Tear free
lcd_setRotation(0);
img.fillRect(0, 0, 536, 240, TFT_RED);
img.setTextColor(TFT_WHITE, TFT_RED);
img.drawString("TEARING TEST",175,100);
lcd_PushColors_Rotated_90(0, 0, 536, 240, (uint16_t*)img.getPointer());
delay(1000);
img.fillRect(0, 0, 536, 240, TFT_GREEN);
img.setTextColor(TFT_WHITE, TFT_GREEN);
img.drawString("TEARING TEST",175,100);
lcd_PushColors_Rotated_90(0, 0, 536, 240, (uint16_t*)img.getPointer());
delay(1000);
img.fillRect(0, 0, 536, 240, TFT_BLUE);
img.setTextColor(TFT_WHITE, TFT_BLUE);
img.drawString("TEARING TEST",175,100);
lcd_PushColors_Rotated_90(0, 0, 536, 240, (uint16_t*)img.getPointer());
delay(1000);
// 90 degree rotate - Fullscreen - Fast but not tear free
lcd_setRotation(1);
img.fillRect(0, 0, 536, 240, TFT_DARKCYAN);
img.setTextColor(TFT_WHITE, TFT_RED);
img.drawString("TEARING TEST",175,100);
lcd_PushColors(0, 0, 536, 240, (uint16_t*)img.getPointer());
delay(1000);
img.fillRect(0, 0, 536, 240, TFT_GREENYELLOW);
img.setTextColor(TFT_WHITE, TFT_GREEN);
img.drawString("TEARING TEST",175,100);
lcd_PushColors(0, 0, 536, 240, (uint16_t*)img.getPointer());
delay(1000);
img.fillRect(0, 0, 536, 240, TFT_PURPLE);
img.setTextColor(TFT_WHITE, TFT_BLUE);
img.drawString("TEARING TEST",175,100);
lcd_PushColors(0, 0, 536, 240, (uint16_t*)img.getPointer());
delay(1000);
// 90 degree rotate - Not Fullscreen - Buggy
int32_t width = 200;
int32_t height = 100;
img2.fillRect(0, 0, width, height, TFT_DARKCYAN);
img2.setTextColor(TFT_WHITE, TFT_RED);
img2.drawString("TEARING TEST",0,0);
lcd_PushColors(0, 0, width, height, (uint16_t*)img2.getPointer());
delay(1000);
img2.fillRect(0, 0, width, height, TFT_GREENYELLOW);
img2.setTextColor(TFT_WHITE, TFT_GREEN);
img2.drawString("TEARING TEST",0,0);
lcd_PushColors(0, 0, width, height, (uint16_t*)img2.getPointer());
delay(1000);
img2.fillRect(0, 0, width, height, TFT_PURPLE);
img2.setTextColor(TFT_WHITE, TFT_BLUE);
img2.drawString("TEARING TEST",0,0);
lcd_PushColors(0, 0, width, height, (uint16_t*)img2.getPointer());
delay(1000);
}
I'll try to fix this, but I thought I would report it too just so you are aware. You'll see the partial updates corrupt the screen in odd ways. Thanks so much for all your help!
@diegomacario
Hi again,
The partial update regions need to conform to the rounding requirements of the screen in portrait orientation even if you're using a logical landscape orientation for your project - as mentioned above and copied with additions here:
/////////////////////////////////////////////////////////////////////////////////////////// If you find that a full screen update for animation is too slow then you CAN use lcd_push_colours() for partial update but there is a caveat. See page 68 and 70 of the RM67162 datasheet.
For both Row and Column Start/End (RASET and CASET registers):
(1) SC[9:0] always must be equal to or less than EC[9:0]. (2) The SC[9:0] and EC[9:0]-SC[9:0]+1 must be divisible by 2. (3) SR[9:0] always must be equal to or less than ER[9:0]. (4) The SR[9:0] and ER[9:0]-SR[9:0]+1 must be divisible by 2.
Failure to 'round off' your update regions to meet these criteria might result in the kind of intermittent 45 degree skewing that looks like tearing but is in fact a restriction of the display hardware. A full screen update avoids the issue as 536x240 meets these criteria. //////////////////////////////////////////////////////////////////////////////////////////////////////
Therefore for full screen update:
SR&SC=0 EC-SC+1 = 535-0+1 = even. SR-Er+1 = 239-0+1 = even.
...which is legal.
So partial updates - especially translational animations - might seem to corrupt the display in an unpredictable manner but by 'quantizing' your region dimensions and start coordinates according to the datasheet stipulations it should work cleanly.
This means that for pixel resolution layout you have to dynamically adjust what you grab from the esp frame buffer (oversizing the grab where needed) and pushing the data to a minus offset datum (where needed). You don't have to worry about this with the TFT_eSPI supported displays as Bodmer already did all the hard work under the hood. Big credit to him.
BTW, I've still got lots of work left to do on these driver changes and adding a partial update formatting function is at the top of my list - hopefully to do this week. I will also add more user friendly rotate options:
Rotate 0 - fast (default) Rotate 90 - fast Rotate 180 - fast Rotate 270 - fast Rotate 0 - tear safe Rotate 90 - tear safe Rotate 180 - tear safe Rotate 270 - tear safe
For partial updates in the non-tear safe modes the lcd_pushColors() function must also be modified. (WIP)
It's a PITA that we can't just set arbitrary region sizes and datums but the datasheet hath spoken! :) I already implemented region update in my LVGL demo so I know the logic is sound. LVGL has embedded functions which help to make it easy. I just need to port the same methods to this TFT_eSPI implementation.
If you're working on it too then that's great - we can share notes.
nik
@diegomacario
Bug found:
In rm67162.cpp line 167 change
t.base.addr = 0x003C00; to t.base.addr = 0x002C00;
This was just a stupid typo in my driver. My bad.
Please try your code again and report back.
Thanks, nik
Thanks so much, that did the trick for me! The ray-tracer is running beautifully now. These ESP32 chips are awesome. Here are some updated videos of the project running with the new driver:
@diegomacario Great work! Yes ESP is awesome! Can't wait for the ESP32-P4. Keep me up to date on your project on my github: https://github.com/nikthefix/General-queries-and-discussion
nik
@nikthefix sorry for troubling you again, but earlier in this thread you mentioned that you have used bitbank2's AnimatedGIF library to play GIFs on the T-Display S3 AMOLED. I'm interested in doing the same.
I saw that in that library there's a nice TFT_eSPI example: https://github.com/bitbank2/AnimatedGIF/tree/master/examples/TFT_eSPI_memory
Since we don't have access to calls like tft.pushPixels
on the T-Display S3 AMOLED, I tried to modify the example to use your driver instead. This commit contains the changes I made, they are pretty concise: https://github.com/diegomacario/Tiny-Ray-Tracer/commit/316e22b115aa57f7cf0f20945a23eb267731a557
The code compiles and runs successfully, but the GIF plays extremely slowly, as you can see in the video below:
I just wanted to ask if you have any advice on how to use that library successfully on the T-Display S3 AMOLED. Thank you!
@diegomacario The default GIF buffer size in that TFT_eSPI example is very small as Bitbank2 thoughtfully didn't want to assume that it would be run on boards with PSRAM. Since it breaks down the GIF frame into chunks and you are calling the full screen pushColors() for every chunk the result is slow. Perhaps look at his other example 'big_mem_demo'. It's much simpler and renders each frame in one go. It's not a TFT_eSPI specific example but with a bit of massaging it's definitely more suited to integration into your project given your hardware. I'll have a go at it myself as I definitely need fast GIFs in TFT_eSPI also. GIFs work flawlessly in LVGL on the T3-Amoled using the native LVGL GIF decoder so we know it's gonna be possible to do it well using TFT_eSPI.
Once you have it working using the full frame GIF buffer / decode cycle then the next step for speed is to push each GIF frame as a sub-region to the display - obeying the rules of odd / even region parameters as outlined above. Otherwise you'll get artifacts.
nik
@nikthefix superb stuff !! Well done on getting it working !
@davidos81 Thanks very much! Still a lot of work to do on it to get it tidy.
nik
This issue is stale because it has been open for 30 days with no activity.
Please add latest version of RM67162 datasheet.
The readily available V0.5 does not show support for QSPI and the colour correction registers detailed do not have any effect. Display dimming / brightness / invert / partial display registers all work as expected as of V0.5 of RM67162 datasheet.