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

Question about time to write Data to IT8951 Framebuffer. #2

Open
tobiasaska opened this issue Aug 20, 2019 · 45 comments
Open

Question about time to write Data to IT8951 Framebuffer. #2

tobiasaska opened this issue Aug 20, 2019 · 45 comments

Comments

@tobiasaska
Copy link

Hello,
I am working with Raspberry Pi 3 and the 10.3" Epaper Display from Waveshare. The refresh rate is very fast but the time to write the data from host frame buffer to IT8951 Frame Buffer is about 10 seconds. This is way to long for my application. Is there any way to make this process faster? Or can write multible images to different Frame Buffers on the IT8951? Has this to do with SPI interface?

@JorgosCoenen
Copy link

From my experiences, the size and detail of the image seems to make a difference. Converting the image to a C-file before or using the IT8951 bmp-conversion function doesn't seem to make too much of a difference.
Experimenting with partial updates where you only have to push a select buffer size can also help.

For now, designing for e-ink screens still seems to require thinking around the limited refresh rate.

But curious if waveshare has any suggestions too!

@tobiasaska
Copy link
Author

From my experiences, the size and detail of the image seems to make a difference. Converting the image to a C-file before or using the IT8951 bmp-conversion function doesn't seem to make too much of a difference.
Experimenting with partial updates where you only have to push a select buffer size can also help.

For now, designing for e-ink screens still seems to require thinking around the limited refresh rate.

But curious if waveshare has any suggestions too!

Thank you for your reply.
The problem does not seem to be the actual refresh rate which is around 450ms. The problem is the time to write the image from host frame buffer to IT8951 frame buffer. This takes 10 seconds using your demo code running on raspberry pi 3. For example when I use the demo program for windows providet by waveshare it doesnt take that long. How can I display a new image every 450ms or at least every second ?

@JorgosCoenen
Copy link

JorgosCoenen commented Aug 30, 2019

I'm not part of waveshare, so I'm not sure... We've also noticed that the Windows application seems faster.
Are you pushing full resolution bmp's? Don't small images or graphics from the other demo functions go faster?

@naluhh
Copy link

naluhh commented Sep 4, 2019

I made it ~10 times faster by not using LCDWriteData but writing my own function that internally send all the data in one call. I also switched to 4BPP instead of 8 and made it again 2x faster. @tobiasaska

@JorgosCoenen
Copy link

That sounds amazing @naluhh!
Any plans to share your changes? Would love to try them out!

@naluhh
Copy link

naluhh commented Sep 4, 2019

I made a quick test yesterday. I'm trying to make it even faster by extracting the picture directly into a 4bpp texture. I'm only planning on doing full screen updates. I'll share some code this week

@tobiasaska
Copy link
Author

I made it ~10 times faster by not using LCDWriteData but writing my own function that internally send all the data in one call. I also switched to 4BPP instead of 8 and made it again 2x faster. @tobiasaska

@naluhh Thank you very much for this piece of information. Thats exacly what i was looking for. I am pretty new to coding. Would you mind sharing your code with me/us?

@naluhh
Copy link

naluhh commented Sep 5, 2019

#3

It's a work in progress. But you can try like this:

make
sudo ./IT8951 path_to_image.bmp

@tobiasaska
Copy link
Author

#3

It's a work in progress. But you can try like this:

make
sudo ./IT8951 path_to_image.bmp

Thank you! I will try this 👍

@JorgosCoenen
Copy link

JorgosCoenen commented Sep 6, 2019

Tried it just now. Very noticeable speed boost! Awesome! Thank you!
I think you also managed to move to 4bpp? Anyway to also include 8bpp as an option? Or would that reduce the performance boost significantly? You mentioned that even with 8bpp your changes were much faster.
My application has some images that require the higher resolution...

@naluhh
Copy link

naluhh commented Sep 6, 2019

@JorgosCoenen 4BPP is the maximum these screens can do anyway. Right now it's decoding the BMP in 8bpp and I then translate it to 4bpp. It would be much faster (less allocation, smaller file etc) to have a 4bpp image (png support it). I'm sure other optimizations could be done.

@JorgosCoenen
Copy link

Aha! What could than be causing the loss of image quality, if it's always 4bpp anyway?
It kind if looks like anti-aliasing or interlacing. Just trying to understand :)

Here are some images: original, and update.

@naluhh
Copy link

naluhh commented Sep 6, 2019

Could you try to replace this line:

stLdImgInfo.usEndianType     = IT8951_LDIMG_B_ENDIAN;

by

stLdImgInfo.usEndianType     = IT8951_LDIMG_L_ENDIAN;

@JorgosCoenen
Copy link

Sure! Seems this makes the "interlacing" more pronounced.
An image.

@naluhh
Copy link

naluhh commented Sep 6, 2019

What's the resolution of your screen?

@JorgosCoenen
Copy link

JorgosCoenen commented Sep 6, 2019

Ah, I'm using the 9.7" screen, so 1200x825. My images or also this resolution.
I now notice that this repository only seems to refer to the 6" display... There doesn't seem to be one for the 9.7"🤨

@naluhh
Copy link

naluhh commented Sep 6, 2019

I'm using the 10.3" one. Odd number of pixels (y axis) might be the problem with your screen. Without access to the hardware it'll be hard for me to fix it. It was working well for me, probably an alignment thing. Meanwhile you can go back to 8BPP. (You'll need to comment the loop, remove the / 2 on buffer size, and switch 4BPP to 8BPP)

@JorgosCoenen
Copy link

Oh wow, hadn't seen that one, looks pretty great.
Alright, looks back to normal (had to keep your "B_ENDIAN") and definitely still faster.

@naluhh
Copy link

naluhh commented Sep 6, 2019

A good chunk of the time goes into turning on the screen, and decoding the bmp image. Both of them could be reduced. Pre-uploading image you want might help too. (the buffer is big enough to store several images)

@JorgosCoenen
Copy link

Yeah, I keep the screen turned on in my application (added freeing the buffer to the bmp-function, instead of always using the cancel-function).

Does the library include anything to upload multiple images and switch between them? Would definitely also be an interesting hack.

@naluhh
Copy link

naluhh commented Sep 6, 2019

the library doesn't support that. Be carefull, don't leave it on too long, you might reduce the lifespan of your screen/controller

@JorgosCoenen
Copy link

JorgosCoenen commented Sep 6, 2019

Thanks for the heads-up! We have had them running for some long periods without noticeable impact so far. The only thing I've noticed is that sometimes the frame we built behind the screen become visible on the display if it's powered off (especially when in sun light). As if it's shining through.

@naluhh
Copy link

naluhh commented Sep 6, 2019

No doubt that you'll reduce your screen lifespan and greatly increase the consumption by doing so

@naluhh
Copy link

naluhh commented Sep 9, 2019

By decoding the image directly into the buffer, allocating only what's needed and optimizing and merging a few spi calls I was able to increase the speed even further. Depending on the raspberry pi you are using you might be even able to change the clock rate doing a 2x or 4x on the upload speed.

@JorgosCoenen
Copy link

Impressive! We've been using both Pi zero's and 3B+'s, depending on the processing/battery required. On the zero's this is probably not possible?

@tobiasaska
Copy link
Author

@naluhh

Wow! You are solving all my problems I had working with the IT8951. You must have a lot of experience on this field. Thank you for sharing your improvements with us!

@naluhh
Copy link

naluhh commented Sep 9, 2019

Can you try to replace BCM2835_SPI_CLOCK_DIVIDER_32 by
BCM2835_SPI_CLOCK_DIVIDER_16 then BCM2835_SPI_CLOCK_DIVIDER_8, BCM2835_SPI_CLOCK_DIVIDER_4(in the init func). (Keep going down until it stop working basically). Stay on the commit of my branch you were.

@JorgosCoenen
Copy link

JorgosCoenen commented Sep 9, 2019

Anything below 16 doesn't work on my Pi Zero (just a flicker in the top left corner).
Slightly faster compared to at 32, yes! Don't have a 3B+ at hand right now, but I could try with that too.

Edit: this is still with the loop commented out and the 8bpp

@naluhh
Copy link

naluhh commented Sep 9, 2019

I'm curious about the result on the 3B+. Could you give me back the results you get?

@naluhh
Copy link

naluhh commented Sep 9, 2019

Also, if you don't care about accuracy, you could switch to 1 bpp buffer, which would divide the transfer duration by ~8 in your case

@JorgosCoenen
Copy link

Ok, did manage to test on a 3B+. Getting the same result as on the Zero, only a flickering rectangle in the top left corner with clock_divider below 16. This rectangle flickers and goes away , the previous image stays on screen.
But again, definitely a speed bump with 16 instead of 32 and I'm not noticing any quality loss.
Full resolution (1200x825) bmp images are pushed in ~1 second (excl. init time).

@naluhh
Copy link

naluhh commented Sep 9, 2019

You could also remove the line

EPD_Clear(0xff);

if you don't plan on showing partials image

@JorgosCoenen
Copy link

Yeah, thanks so much, this has been really helpful!

Do you think having the images converted into arrays and using the EPD_DrawMatrix() function would be faster than the Show_bmp() function? I didn't see much of an improvement when we did this on the original code, but maybe with your changes?

@naluhh
Copy link

naluhh commented Sep 9, 2019

I don't know, I personally switched to 4bpp png for performance/size reasons. (You can see the tip of my branch with libpng)

@naluhh
Copy link

naluhh commented Sep 10, 2019

I optimized the maximum I could. I think someone with more knowledge on the subject could go even further. For my resolution (1872*1404) I'm able to reach 0.9 sec / image. For 1200x825 I reached 0.63 sec / image. The buffer upload takes 60% of the time, so if you are able to pre-upload your images, or upload severals images at the same time you could reach higher speed (the other part, IT8951LoadImgStart, takes 40% of the time but I don't have any clue on how to increase it's speed).

@JorgosCoenen
Copy link

Really terrific results! Thanks again!

Could you say a little more about using png's instead of bmp's? I want to keep the same image quality (8bpp I guess), but using png's would really help our workflow and performance (I'm generating images in d3.js and having to convert them to bmp's in JS is not trivial for me and takes some time/processing power).

@naluhh
Copy link

naluhh commented Sep 10, 2019

As I said, 4bpp is the maximum quality you'll get. If I had access to your screen, I could certainly fix it. The tip of my branch works with 4bpp png as input. Here is a video with a loop decoding png + uploading to the buffer + updating the screen

test-video-gif-fdp

@JorgosCoenen
Copy link

Do you mean that the display will not go above 4bpp, or the input image png has to be 4bpp?

I'm trying your branch now.

I don't understand why, but one of my Pi Zero will not go below 32 for the BCM2835_SPI_CLOCK_DIVIDER. It messes up the initialisation at least. I noticed it before too, when I wasn't using your latest branch with the png, but was just trying the lower values.

sudo ./IT8941 test-4bpp.png
"****** IT8951 ******
Panel(W,H) = (1784,829)
Image Buffer Address = 19F1F0
FW Version = {8?;?9~
LUT Version = o<>9"

When I put it at 32, it initialized correctly, but still crashes afterwards (whole Pi becomes stuck):
sudo ./IT8941 test-4bpp.png
"init start
****** IT8951 ******
Panel(W,H) = (1200,825)
Image Buffer Address = 11A1E0
FW Version = SWv_0.2.1T
LUT Version = M841"

@naluhh
Copy link

naluhh commented Sep 10, 2019

I hardcoded my screen size, that's why (and also require a 4bpp png as input). The display is 4 bpp, therefore having an image higher than that is pure waste.

@pshkvsky
Copy link

pshkvsky commented Nov 5, 2019

@naluhh how do you create 4bpp png?
could you please add some examples of files and the process.
Thank you!

@naluhh
Copy link

naluhh commented Nov 6, 2019

I made a repo @pshkvsky https://github.com/naluhh/4bpp-converter/

@nest000
Copy link

nest000 commented Dec 22, 2019

hey @naluhh .. you implementation regarding the socket stuff looks very promising, but i cant get it run. Can you provide a working example?

I could get the socketserver working and got also client connection messages, when i did:

nc localhost 8888 < ~/test-out.png

i got always the message that the file is not valid. i tried also to supply the filename only, but without success.

nc localhost 8888 < <(echo ~/test-out.png)

what do i wrong here? ;)

May thanks in advance!

@naluhh
Copy link

naluhh commented Dec 22, 2019

it's expecting a local path:
||Ufilename.png|| will make the client look for filename.png (4bpp png) and update it to the screen. If it doesn't have the file, it'll request it by sending a ||Dfilename.png|| to the server and expecting it to send it as png. It'll then cache it locally. I don't provide support for it, sorry

@flashspys
Copy link

You can convert any image to a 4bpp via imagemagicks's convert a.png -depth 4 b.png. I'm running @naluhh 's server, it's working really great!

@aditya111222
Copy link

  1. Can i Store the Multiple image Buffer into IT8951
  2. Can i load the one image half half buffer into IT8951 and then after Display

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

7 participants