Uint8Array over SPI #7668
Replies: 1 comment
-
Posted at 2020-02-01 by Robin Sat 2020.02.01 What is the value of '_bufferSize'?
Yes, check the MDN example below > 'but seemingly doesn't update the RAM of the paper' Might be SPI timing or how the display handles a specified number of inboound chars. Without the datasheets, and all of the source code, not attempting a guess.
Have these resources been found, good examples on UintxxArray() usage
It appears the array is initialized with one char, not every location Check the example using method fill()
Posted at 2020-02-01 by Raik _bufferSize is the length of the graphics buffer, in my case 5808 bytes (176*264/8). So the code is this (inside a lot more code):
So what it does is, when flip is called, transmit the buffer data to the papers ram. It is actually only a modification of the SSD1606 module code. In there the flip function it does exactly the same: transmit the buffer data via SPI as an Uint8Array (as I just learned, more a view to the buffer?). Otherwise I can only think of a problem in transmitting speed. I played around with the SPI baud rate (set it lower) but to no avail. I mean, the code does work, but writing 2 buffers (one for red, one for black) takes about 3.5s each + the 15s update cycle of the paper. I think there is potential for speeding up things. Posted at 2020-02-02 by @allObjects 3.5 seconds for 176264 (/89) bits makes about 15k baudrate... indeed very slow... But I have to break bad new to you, it is what it is, as the specs say: https://www.waveshare.com/2.7inch-e-paper-hat-b.htm : 15secs for a refresh / full update, and it has nothing to do with Espruino or any other driving platform. Why the technology is so slow? I assume it is inherent to the electrophoresis, which by matter of facts takes time. The discovery - https://en.wikipedia.org/wiki/Electrophoresis - speaks of migrating - vs the term of moving - in a liquid. Particles with different properties and color move on different polarity in different direction with different speed in a liquid, which allow the third color (simplified in a nutshell how ePaper works). I assume the slave device does a lot of clock stretching, which should be visible by looking at the clock with an oscilloscope. I'm pretty sure that ePaper displays do not have built-in buffer. No need for, because after the pixel (distribution of colored particles in cell) has changed, it it stays. No refresh (of same state) is needed. Even with a built in buffer, it could not be made faster. Yes the update of the buffer could be made faster, and some build it logic with more buffer could figure out what to update and go and update only the changed pixles (cells) and then go to sleep after all is updated. ePaper are for applications that 'rarely' change the content... rarely compared to how long a content stays displayed until updated. What is the application you have in mind and why did you choose this display technology versus other available ones? If the answer is "low power", then you may take a look at this paper: https://www.mdpi.com/2071-1050/7/8/10854/pdf Posted at 2020-02-02 by Raik
Yes I know it updates slowly and I understand the technology behind it. And I chose it merely because the technology itself intrigues me.
From what it says in the documentation it actually has two buffers: one for old data and one for new data. I guess it is because the display will do other update waveforms if the pixels didn't change between updates. I think writing the data in the for loop might be slow additionally because of pulling the pins high/low before writing (overhead?). I will try to do a time measurement on the Arduino example, just to see what speed the display is capable of receiving. The Arduino example uses 4M baud rate if I see correctly. Posted at 2020-02-02 by Raik Ok, so I did a little more testing and sending the data as Uint8Array only writes the first byte of the array to the papers RAM, see pictures (first (red one) is actual, second is supposed to be). Strange. Could still be an issue with the papers ability to handle all the data transferred to quickly maybe? I lowered the baud rate to 100. It slows everything else down of course, but sill no success. Just read the specs for the controller. Seems like it supports clock rates up to 20MHz.
Attachments: Posted at 2020-02-03 by Robin Sun 2020.02.02
At L9a
Was an attempt made to init the Uint8Array using the suggestions, one of which is in post #9 found in the first link of post #2 above, and an attempt to replace L10 with those suggestions in the code block in post #3 above? When done, what is the output? Looking at L26 L27 L30 L31, are CS and DS backwards? Should CS be toggling with the data as input, then the data line would only \* *see* \* a one byte state change! Posted at 2020-02-03 by @allObjects @raik, took a look at the SSD1606 and IL91874 controller doc. Indeed, the controller has data buffers. I could though find not much how they are used. I assume it is for optimization not only for time performance, but also for quality performance, such as managing the ghosting. Reading thru all the possible OTP and runtime settings makes me question the readiness of the technology for easy use. But this does not mean not to be curious why the data transfer is that slow. The controller has a busy signal output... and looking at the full cycle of an update from powering on the device, preparing it for data reception, to finally shut down again could explain this: shut down has to wait until the controller has updated the display cells. What I did not like in the module was the byte-wise operation of clear display screenbuffer with desired color (.csb(cb,clr)). Going back and forth between applications JS and Espruino firmware for each byte slows things don for sure. Alternative: sacrifice memory for another buffer, fill it with the desired value, and send that to the controller (I do not know if .csb(cb ,clr) is in the path of your code). Various items I cannot understand:
Another comment I'd like to make: I read about controller and displays the documentation mentioned that the OTP / LUT data is (usually) factory set for best display (quality) performance - of the particular display on which the controller is mounted. Messing with that I reserve for myself for a later stage (invoking .ini()). I have a 1.54" 200x200 tri-color ws display sitting around for a while now, and I noticed the the originally white background 'turned rosy'. May be time has come to fool around with it... to co-bang-head-on-wall ... ;\ or better: |:| (flat forehead). Posted at 2020-02-03 by Raik I'll test again tonight to see (proof ;-)) that the buffer is indeed 5808 bytes of data, not just one byte.
I noticed that the OTP works better for me, the custom LUTs turn the red into rosy (like your display sitting around). But: I saw that Ben Krasnow from YT channel Applied Science made a nice video about hacking the ePaper update rates. That'll be next when getting the data transfer fixed up (if possible). :-)
Sounds good |:| Posted at 2020-02-03 by @gfwilliams This is really odd - I don't suppose you have some kind of oscilloscope you could use to check if the data is being sent?
Should be perfectly fine, and we do it all over the place in different modules. You could give software SPI a go in case it makes a difference? Posted at 2020-02-03 by Raik
Nope, I'm not the hardware guy ;-)
I assumed so as well. I'm quite confident it is an issue with the paper itself.
I did and it didn't change a thing. I'll investigate more tonight. Posted at 2020-02-03 by @allObjects Pretty interesting and revealing this Ben Krasnow presentation. What it kind of confirmed to me is the quick transmission is with 20Mhz to get the data buffers updated, but that transmission follows the update of the display cell by cell with looking up the waveform and pushing it out. The presentation also proves that speed is inverse to display quality (contrast). Btw, very neat oszi - a far cry from what I ever can dream of. Posted at 2020-02-03 by Raik
Actually, you can (should?) set the waveform on initialization of the display. I guess it is then stored on the chip. In the SSD1606 implementation it is done the same way.
Posted at 2020-02-03 by @allObjects I don't think you should (have to) adjust the wave forms: they are factory set when display was tested and initial (test) image data was loaded onto, but for sure you can. Posted at 2020-02-03 by Raik
I also tried initializing it as Uint16, same result.
I tried switching hard- and software-wise, with negative result. Posted at 2020-02-03 by Raik So, I think I found the culprit. I (again) had a look at the [display driver specs](https://www.good-display.com/IL91874 V0.3cd82.pdf) and on page 16 it shows the cycle graph(?) for the 4-wire SPI interface, see attached image. Below the graph it says:
That and the rising flank of the CSB signal after the 8 databits on the right, leads me to believe that CS needs to be pulled down and up again for every byte written. So I changed my write function like so:
Now this does not work anymore, because CS only changes once right before all the data writing. Changed it back to:
immediately starts working. I assume that
also pulls down csPin only once. So now the questions would be: would it be feasible to create a native SPI write function that pulls the cs(nss) pin down for every byte written and does that make sense? Would my case still benefit speedwise? Otherwise I would be stuck to my single bytes write algorithm and the speed bottleneck it causes. EDIT: Just stumbled across Espruinos capability of inline C code. I guess that could speed up the data transfer loop...? Attachments: Posted at 2020-02-04 by @allObjects On lower level function paths with multiple writes, manage the writing of the -csPin yourself because you know what is going on. For higher levels, you handle it in the top level function. Yes, inline C (and compiled methods) are faster as long as you have not to resolve references by name. If you can pass all data into the C code at once, complete everything within, that works great. Works especially great for bit manipulations within contiguous Uint8..32Arrays. For calling functions / methods that expect the caller to be in JavaScript adds some overhead... after all, the main is in JavaScript... and if something is too slow and used often, it usually gets into the firmware (and built-in module or even omni-present class/function). For most situations - especially with Graphics buffer - @gfwilliams has already taken care of by providing options in the setup. If you though think about partial update out of a graphics buffer, the pulling out and prepping the array for the display, it is for sure helpful (I used it here: Efficiently moving things around in zig-zag Graphics buffer visualized w/ 24/32 bpp displays / neopixel strings). Posted at 2020-02-04 by Robin Mon 2020.02.03
Yes, by a small amount. But, . . . isn't the data bit rate set by the setup of SPI? (yes) As the image in #16 is helpful here, has the use of an inexpensive logic analyzer been used?
What about SPI.send() vs SPI.write() ? > [SPI syntax for receive string clarification and sanity check please](http://forum.espruino.com/conversations/336724/#comment14838658) Posted at 2020-02-04 by Raik
Setting the baud rate, doesn't seem to matter much.
There is definitively switching overhead to the CS pin, as mentioned here.
No. Didn't fiddle with that.
Tested, works, but same speed |
Beta Was this translation helpful? Give feedback.
-
Posted at 2020-01-31 by Raik
Hi,
while I am fiddling around with driving an epaper display with Espruino Wifi I'm still having issues with writing data. Just to be sure:
Is this:
different from that?
First one actually writes the RAM of the paper correctly and after update it will display correcty, but its slow (3.5s for 5800bytes).
Second one is fast, but seemingly doesn't update the RAM of the paper, because after update it still displays the same.
In the reference it says:
Beta Was this translation helpful? Give feedback.
All reactions