9names / uc8151-rs

A Rust port of Pimoroni's uc8151 driver, as used on badger2040
7 stars 2 forks source link

Would it be difficult to add greyscale? #5

Open Kuratius opened 1 year ago

Kuratius commented 1 year ago

It seems that the LUTs can be modified, and to my understanding greyscale is just a very advanced type of ghosting. https://github.com/adafruit/Adafruit_CircuitPython_UC8151D/blob/main/adafruit_uc8151d.py

The adafruit version of this driver seems to include some sort of grayscale LUT already, although I havent tested it.

Kuratius commented 1 year ago

Nevermind, this might just be a startup/flashing sequence. Still, it's probably possible to figure something out. I'll see if I can find any more information.

Kuratius commented 1 year ago

http://essentialscrap.com/eink/Driving_E_Ink_Displays.pdf

https://confit.atlas.jp/guide/event-img/idw2019/EP1-3/public/pdf_archive?type=in

Kuratius commented 1 year ago

https://www.youtube.com/watch?app=desktop&v=MsbiO8EAsGw This seems to work with IL0373, so some of it may be relevant.

Kuratius commented 1 year ago

image

parsing the LUTS from the pimoroni driver gives this under the assumption that the voltage value is signed note that this may still be a wrong way to interpret the voltage it doesnt help that half the LUTS are identical

Kuratius commented 1 year ago

http://dmitry.gr/?r=05.Projects&proj=29.%20eInk%20Price%20Tags

Kuratius commented 1 year ago

It seems like this is purely a LUT issue, and has been done by other people before

Kuratius commented 1 year ago

https://goodereader.com/blog/product/2-9-inch-epaper-display-grayscale-gdew029t5d-goodisplay-partialupdate-einkdisplay

Seems to be sold as a greyscale display, maybe some of the sample codes contain a waveform that can be copied

Kuratius commented 1 year ago

Technique for getting 2 extra gray levels (total 4): Drive display to white with BW waveform

Lie to display about previous state Drive some pixels to black using WB waveform to update Pixels that remain white should use BW to update. Insert BB and WW waveforms that have adjusted timings, but not voltages (due to unknown format), use BB to drive white pixels gray shade 1, WW to drive black pixels gray shade 2.

More should be possible if waveforms can be changed on the fly, but will obviously take very long to update. Ideally you'd want to never drive pixels to white/black if they are already that color, but that makes things a bit more complicated. Since the BW/WW waveforms are identical, I interpret this as them being originally intended for refreshing the display from an unknown or random state.

Kuratius commented 1 year ago

I am not familiar with the codebase for this driver, but the driver used in the micropython project linked on the goodereader page seems to transmit the previous screen state before triggering a refresh, so I would assume this one should or could be made to work similarly.

9names commented 1 year ago

This driver is based on the original release of the pimoroni C driver. There was a rewrite started before I had finished porting, but it didn't appear to have any useful changes. I have no idea how this development relates to the python driver. Are they doing a partial refresh somehow? I would have expected an inverted version of the current image in that case...

Kuratius commented 1 year ago
def EPD_init():
    EPD_W21_Init()  #Electronic paper IC reset

    EPD_W21_WriteCMD(0x04)  
    lcd_chkstatus()#waiting for the electronic paper IC to release the idle signal

    EPD_W21_WriteCMD(0x00)      #panel setting
    EPD_W21_WriteDATA(0x1f)     #LUT from OTP£¬KW-BF   KWR-AF   BWROTP 0f   BWOTP 1f

    EPD_W21_WriteCMD(0x61)    #resolution setting
    EPD_W21_WriteDATA (0x80)   #128      
    EPD_W21_WriteDATA (0x01)   #296
    EPD_W21_WriteDATA (0x28)    

    EPD_W21_WriteCMD(0X50)          #VCOM AND DATA INTERVAL SETTING         
    EPD_W21_WriteDATA(0x97)     #WBmode:VBDF 17|D7 VBDW 97 VBDB 57      WBRmode:VBDF F7 VBDW 77 VBDB 37  VBDR B7
#display 
def PIC_display(picData):
    #Write Data
    EPD_W21_WriteCMD(0x10)       #Transfer old data
    for i in range(4736):
        EPD_W21_WriteDATA(0xff)

    EPD_W21_WriteCMD(0x13);          #Transfer new data
    for i in range(4736):     
        EPD_W21_WriteDATA(picData[i]) #Transfer the actual displayed data

    #Refresh
    EPD_W21_WriteCMD(0x12)      #DISPLAY REFRESH    
    utime.sleep(0.01)           #!!!The delay here is necessary, 200uS at least!!! 
    lcd_chkstatus()          #waiting for the electronic paper IC to release the idle signal
#Clear screen
Kuratius commented 1 year ago

Relevant section

9names commented 1 year ago

Thanks! Looking at the data sheet, this does appear to be for partial refresh - in black+white mode you send old data with command 0x10 (dtm1), new data with 0x13(dtm2). It's less clear about what to do next - it looks like you should send data stop command 0x11(DSP) but the python calls display refresh 0x12 (DRF)

9names commented 1 year ago

Actually later in the datasheet they use DRF so perhaps that is the intended order of operations. I haven't looked at the rust code for a while so can't remember what we do...

9names commented 1 year ago

I had a quick go at getting fast update mode going - it's not working correctly yet. https://github.com/9names/uc8151-rs/commits/fast_update

Reading through the datasheet, I forgot that I haven't really implemented any of the read commands, so I made a start on that as well, since we should check the status at least on Data Stop (DSP)

9names commented 1 year ago

Ah. Read commands are wasted on badger2040 - even though MISO is on the schematic, it's not connected to the display. Well that was a waste of time :/

Kuratius commented 1 year ago

is this the same on the 2040w?

9names commented 1 year ago

Yes. https://cdn.shopify.com/s/files/1/0174/1800/files/badger_w_schematic.pdf?v=1675859004

Kuratius commented 11 months ago

If you happen to have any tools that can measure the reflectivity of the display with good time resolution (high fps camera, or a photodiode hooked up to an oscilloscope or rpi) it may be possible to fit a model to the display so that waveforms don't have to be tested manually to see the the result. grafik e.g. a graph like in this paper + equation of motion (EOM) + some simplified model for the reflectivity
grafik grafik

grafik

you get stuff like this.

9names commented 11 months ago

Fascinating. I do not have fancy tools for measure reflectivity, pi/pico + photodiode would be the best I could do.

Speaking of cool e-ink stuff, you seen this? https://github.com/Modos-Labs/Glider I don't think it helps us at all, but the existence a 60/120hz e-ink display blows my mind.

Kuratius commented 11 months ago

It is not too surprising, but it will probably draw a lot of power. 2x refresh rate should be 4x power use, for very fast refreshes I expect it could go up to 16x. So only really interesting for stationary displays. Eink displays are essentially very weird particle accelerators, so there isn't a direct limit as long as you have power and uniform particles (and keep track not to make them clump together at one end).

Past a certain speed there may be some fluid flow effects that are hard to predict, but that just means you need better modeling. It is not a speed limit.

Kuratius commented 11 months ago

You need to move the black pigment a specific distance s in time t to achieve a color change. Meaning a velocity v=s/t

We know from stokes law that for spheres F=6π eta R v Electric force on a charged particle is qE

E is voltage/distance so

qE=6π eta R v qV/s=6π eta R s/t

V=6π eta R s^2/(qt). t=1/framerate (let's call it f) so V=6π eta R s^2 f/q

So for double the framerate you would expect double the voltage.

Also typically power draw scales with the square of the voltage, so you would expect that 2x voltage means 4x power draw.

The other thing to consider is that Stokes Law is an approximation for low velocities, you would expect that for high velocities it is invalid and you may have a quadratic relationship between force and velocity, so your voltage may scale with s^3/t^2, (meaning double the framerate is now 4x the voltage and 16x the power draw)

Kuratius commented 11 months ago

You can also work with reduced contrast + more opaque fluid to reduce the distance particles need to move.

Kuratius commented 5 months ago

https://github.com/sqfmi/badgy/tree/master/examples/grayscale

Might be interesting, will need to check if the lut tables are compatible. Posting so I don't forget.

Display seems the same size as the badger, no idea if it is actually the same.

Kuratius commented 3 months ago

https://github.com/antirez/uc8151_micropython Seems that someone has already implemented it.