NiLuJe / FBInk

FrameBuffer eInker, a small tool & library to print text & images to an eInk Linux framebuffer
https://www.mobileread.com/forums/showthread.php?t=299110
GNU General Public License v3.0
315 stars 23 forks source link

[RFC] Remarkable support #41

Closed tcrs closed 4 years ago

tcrs commented 4 years ago

I'm afraid there is much I don't understand about eink screens. I added a rather arbitrary mapping of the waveform modes in get_wfm_mode. I'm not sure what the dither bit should be set to in the update ioctl. Among other things...

Could you take a look and give me some advice on this? What I've got at the moment is happily displaying some text which is the most important hurdle for me at the moment (I'm porting this to use in my koreader port really).


This change is Reviewable

NiLuJe commented 4 years ago

Looks fairly okay for a first stab ;).

(And I'm hoping the ifdeffery mess wasn't too awful, especially since the recent cleanup ;)).

NiLuJe commented 4 years ago

At a very quick glance at the driver, the actual dithering value doesn't matter much?

https://github.com/reMarkable/linux/blob/zero-gravitas/drivers/video/fbdev/mxc/mxc_epdc_v2_fb.c#L2605

https://github.com/reMarkable/linux/blob/zero-gravitas/include/uapi/linux/mxcfb.h

(I'm not on my main dev box, and Kindle/Kobo kernels are only available as tarballs, so I can't have a quick comparative look at them, so take this with a grain of salt ^^).

NiLuJe commented 4 years ago

It's also highly unclear to me which version of the driver it's actually supposed to use, especially when looking at the commits in the more up-to-date zero-gravitas_4.9 branch, which mostly appear to target the older driver (https://github.com/reMarkable/linux/blob/lars/zero-gravitas_4.9/drivers/video/fbdev/mxc/mxc_epdc_fb.c && https://github.com/reMarkable/linux/blob/lars/zero-gravitas_4.9/include/uapi/linux/mxcfb.h).

In which case, that dithering flag is actually meaningless (because it's only supported by the v2 driver), and I have no idea why the kernel actually supports the ioctl with that updated, larger struct ^^.

(Although I have seen some weird hoop-jumping being done before in the name of backward compatibility, so, who knows ^^).

NiLuJe commented 4 years ago

The config appears to confirm that the v2 driver is unused, so you can pretty much forget about all that, and always set dithering & quant_bit to 0 ;).

Still puzzled as to why they kept the updated struct, though.

But I can roll with that, it's certainly less messy than what I've seen before, which is either a different ioctl/struct combo for each device, or a device with support for 2 or 3 different ioctls with a slightly different struct each time ;).

NiLuJe commented 4 years ago

I wouldn't mind a link to the upstream Kernel repo in the bundled mxcfb header copy, by the way ;).

I probably ought to do that myself for the Kindle & Kobo ones, actually ^^.

NiLuJe commented 4 years ago

Extremely minor nitpick: I'm guessing they care about the peculiar casing of the reMarkable name, so I'd double-check that, too ;).

NiLuJe commented 4 years ago

And, obviously, because I kind of forgot to say it in my excitement: thanks for working on this ;).

NiLuJe commented 4 years ago

I'd also add a small identify_remarkable to fbink_id.c, just to set the name/codename (which appears to be zero-gravitas), and to set the DPI (226?).

It'll also come in handy if you want to implement fbdepth (as being able to switch to 8bpp would improve performance in KOReader, because RGB565 is the worst). To that end, I wouldn't mind having a peek at the console output from a random print, mainly to check what the "standard" rotation is ;).

tcrs commented 4 years ago

Thanks for the feedback, I've had a go at the improvements you suggested. The waveform mode mapping is still not 1:1.

Here's the output from a simple fbink invocation, this is just after starting xochitl so should be set up in the default way.

remarkable: ~/ ./fbink 'HELLLO'
[FBInk] Detected a reMarkable
[FBInk] Clock tick frequency appears to be 100 Hz
[FBInk] Screen density set to 226 dpi
[FBInk] Variable fb info: 1404x1872, 16bpp @ rotation: 1 (Clockwise, 90°)
[FBInk] Fontsize set to 24x24 (IBM base glyph size: 8x8)
[FBInk] Line length: 58 cols, Page size: 78 rows
[FBInk] Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes
[FBInk] Pen colors set to #000000 for the foreground and #FFFFFF for the background
Printing string 'HELLLO' @ column 0 + 0px, row 0 + 0px (overlay: N, no BG: N, no FG: N, inverted: N, flashing: N, centered: N, halfway: N, left padded: N, right padded: N, clear screen: N, waveform: AUTO, dithered: N, nightmode: N, skip refresh: N, font: 0, font scaling: x0)
Next line should start @ row 1
tcrs commented 4 years ago

Also, I'm using fbdepth when launching koreader now to set the panel to 8bpp and it seems to be working, does appear a bit snappier (but I could be imagining it...)

NiLuJe commented 4 years ago

Great, thanks :).

Don't worry too much about the waveform mapping, I'll take a pass at it tomorrow if I can (I should be able to push to your branch), that'll probably be easier than a few more back & forth, especially since you don't have any other device to compare to ;). I'll just ask you to double-check that I didn't do anything obviously stupid when I'm done ;).


Good to know about fbdepth (and it being snappier is definitely the end goal. A quick, obvious test is panning a full-screen cover, for instance. You also get free software dithering as a bonus ;).). Quick question, though: how are you calling it, exactly? I assume you're omitting the -r, --rota switch?

I'll probably also set a few flags to make that not entirely broken, to that end, you can try running the "rota" tool from the utils folder (it should be built alongside fbdepth w/ the utils target) and posting the output, that should confirm whether there's any weird crap happening on rotation like on some Kobo devices ;).

tcrs commented 4 years ago

I'm currently just using fbdepth to set the depth yea, I've so far left the rotation at the default.

Here's the output of rota, I assume it means more to you that it does to me :)

remarkable: ~/ ./rota 
Variable fb info: 1404x1872, 16bpp @ rotation: 1 (Clockwise, 90°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes

FB_ROTATE_UR to FB_ROTATE_CCW, +1 increments
Setting rotate to 0 (Upright, 0°)
Rotate is now 0 (Upright, 0°)
Variable fb info: 1872x1404, 16bpp @ rotation: 0 (Upright, 0°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 3776 bytes
Setting rotate to 1 (Clockwise, 90°)
Rotate is now 1 (Clockwise, 90°)
Variable fb info: 1404x1872, 16bpp @ rotation: 1 (Clockwise, 90°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes
Setting rotate to 2 (Upside Down, 180°)
Rotate is now 2 (Upside Down, 180°)
Variable fb info: 1872x1404, 16bpp @ rotation: 2 (Upside Down, 180°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 3776 bytes
Setting rotate to 3 (Counter Clockwise, 270°)
Rotate is now 3 (Counter Clockwise, 270°)
Variable fb info: 1404x1872, 16bpp @ rotation: 3 (Counter Clockwise, 270°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes

FB_ROTATE_UR to FB_ROTATE_CCW, +2 increments
Setting rotate to 0 (Upright, 0°)
Rotate is now 0 (Upright, 0°)
Variable fb info: 1872x1404, 16bpp @ rotation: 0 (Upright, 0°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 3776 bytes
Setting rotate to 2 (Upside Down, 180°)
Rotate is now 2 (Upside Down, 180°)
Variable fb info: 1872x1404, 16bpp @ rotation: 2 (Upside Down, 180°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 3776 bytes

FB_ROTATE_CW to FB_ROTATE_CCW, +2 increments
Setting rotate to 1 (Clockwise, 90°)
Rotate is now 1 (Clockwise, 90°)
Variable fb info: 1404x1872, 16bpp @ rotation: 1 (Clockwise, 90°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes
Setting rotate to 3 (Counter Clockwise, 270°)
Rotate is now 3 (Counter Clockwise, 270°)
Variable fb info: 1404x1872, 16bpp @ rotation: 3 (Counter Clockwise, 270°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes

FB_ROTATE_UR to FB_ROTATE_CCW, +2 increments, intermerdiary rota if ==
Setting rotate to 0 (Upright, 0°)
Rotate is now 0 (Upright, 0°)
Variable fb info: 1872x1404, 16bpp @ rotation: 0 (Upright, 0°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 3776 bytes
Setting rotate to 2 (Upside Down, 180°)
Rotate is now 2 (Upside Down, 180°)
Variable fb info: 1872x1404, 16bpp @ rotation: 2 (Upside Down, 180°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 3776 bytes

FB_ROTATE_CW to FB_ROTATE_CCW, +2 increments, intermerdiary rota if ==
Setting rotate to 1 (Clockwise, 90°)
Rotate is now 1 (Clockwise, 90°)
Variable fb info: 1404x1872, 16bpp @ rotation: 1 (Clockwise, 90°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes
Setting rotate to 3 (Counter Clockwise, 270°)
Rotate is now 3 (Counter Clockwise, 270°)
Variable fb info: 1404x1872, 16bpp @ rotation: 3 (Counter Clockwise, 270°)
Fixed fb info: ID is "mxc_epdc_fb", length of fb mem: 10813440 bytes & line length: 2816 bytes

Let me know if there is any other things it would be useful to see the output of.

tcrs commented 4 years ago

I just added some default rotation settings to the deviceQuirks which seem to work OK. I'm not sure if I should be setting ntxRotaQuirk = NTX_ROTA_SANE as the comment says that expects boot rotation to be 0 I think. These settings make fbdepth -r -1 set the rotation to the proper portrait rotation for the remarkable at least.

NiLuJe commented 4 years ago

That was precisely what I was planning to do ;).

NiLuJe commented 4 years ago

Although, yeah, the comment in the enum is a bit misleading, as it's specific to the Kobo Libra.

In practice, it means no rotation shenanigans, and honor bootRota as the "native" Portrait, which is exactly what's needed here, too.


I'll add a bunch of comments to make that clearer ;).

NiLuJe commented 4 years ago

Okay, I've hopefully untangled the get_wfm_mode mapping...

As a quick test, because it might come in handy for KOReader to have a definitive answer on that front, can you check if displaying an image w/ A2 (i.e., fbink -W A2 -i img.png) actually crushes it to a bitonal result?

tcrs commented 4 years ago

Okay, I've hopefully untangled the get_wfm_mode mapping...

Thanks :)

As a quick test, because it might come in handy for KOReader to have a definitive answer on that front, can you check if displaying an image w/ A2 (i.e., fbink -W A2 -i img.png) actually crushes it to a bitonal result?

Yea it looks like it does, drawing with A2 on a cleared screen just draws the black bits in the image. Running again with the default settings draws full details.

NiLuJe commented 4 years ago

@tcrs: Yay!

That'll allow me to play with the constant names a bit in the header to make this all slightly less confusing, and this is good to go, thanks :).

I'll be tagging a release soon-ish, but if that doesn't happen soon enough for the KOReader bits, don't hesitate to bump FBInk to a post-merge commit in koreader-base (i.e., the master branch is currently and will be kept in a sane state) ;).

NiLuJe commented 4 years ago

As an additional test, does something similar happens with GL16, or do you get proper shades of gray?

(I'm wondering if it's actually GL16, or GC4).

In either case, it's a far less interesting mode in practice (well, GL16 has its use in theory, but not in practice on a device with GL16_FAST), and it can be a bit weird, so do try after a separate screen clear (because if the fb content doesn't "change", both of 'em are optimized away, so a double-refresh with those is essentially a no-op, even if the content was actually redrawn, as long as it's identical).

tcrs commented 4 years ago

As an additional test, does something similar happens with GL16, or do you get proper shades of gray?

(I'm wondering if it's actually GL16, or GC4).

In either case, it's a-W GL16 -i fbink_image.png far less interesting mode in practice (well, GL16 has its use in theory, but not in practice on a device with GL16_FAST), and it can be a bit weird, so do try after a separate screen clear (because if the fb content doesn't "change", both of 'em are optimized away, so a double-refresh with those is essentially a no-op, even if the content was actually redrawn, as long as it's identical).

./fbink -c; ./fbink -W GL16 -i fbink_image.png draws the image but it flickers constantly for about 10 seconds then settles into a poor reproduction of the image but with a few gray shades. Looks pretty worrying when it is happening! GL16_FAST looks basically the same to my eyes (lots of flickering followed by a bad image).

I saw a similar effect when I was first porting koreader (and just choosing the waveform modes at random).

NiLuJe commented 4 years ago

Huh. That's... weird :D. But good to know nonetheless, thanks ;).

NiLuJe commented 4 years ago

Sidebar: if you (or anyone else with shell access to a reMarkable, really) want to dig into this further, I can whip up the usual strace patch/build to decode mxcfb ioctls, and then it's just a matter of strace'ing the official app's ioctls while doing various different things to see what exactly it's using and when ;).

(This is slightly more practical that what the libremarkable guys have been doing, which is an LD_PRELOAD hack, AFAICT).

NiLuJe commented 4 years ago

Okay, said strace patch is done ;).

It should then be as easy as running ./strace -fitv -e trace=ioctl -X verbose -p $(pidof xochitl) to see what makes it tick ;).

strace-remarkable.tar.gz

(Hopefully, I didn't do anything stupid. If I did, strace will segfault on the first mxcfb ioctl ^^.).

NiLuJe commented 4 years ago

Hmm, see also https://github.com/NiLuJe/FBInk/commit/ffcd9830f2a8c653b99b061c8dd8c78a3ad3a384

Fair warning: I'm terrible at this stuff, and I don't have an IDA Pro license, so this is cobbled together via objdump ;).

Speaking of, @tcrs, I wouldn't mind an updated copy of that (libqsgepaper.a & xochitl), as what's available in the libremarkale repo is over two years old ;).

EDIT: Oh, but libqsgepaper.a is part of the SDK :).

tcrs commented 4 years ago

Here's a few captures using that strace binary & the options you said. I grepped all the mxcfb ioctls out of the full trace (there's constant trace noise from some networking stuff going on).

This one is me just moving around the ui, opening settings, searching etc. ui.log

This is drawing a load of random squiggles and then erasing most of them again drawing.log

This is rendering a single page of a pdf (xochitl really does take about 30s to do that)... pdf.log

NiLuJe commented 4 years ago

Oh, cool, thanks ;).

That seems to confirm what I dug out of libqsgepaper.a, and that the dither_mode/quant_bit fields are used uninitialized here (as is alt_buffer_data), which leads to a lot of confusing garbage if you try to make sense of it ;p. And it shines a light on that weird TEMP constant, which appears to only be used for Mono/DU.

The only question mark left being that "Highlight" mode (currently mapped to REAGL), which I'd take to mean A2? How does it fare with image content w/ FBInk (same test as before ;)).

EDIT: While we're there, I wouldn't mind a test of DU, too (fair warning: if it behaves like on other devices, it may not actually end up displaying much of the image at all).

NiLuJe commented 4 years ago

Oh, err, it turns out the actual header is part of the SDK... \o/

#ifndef EPFRAMEBUFFER_H
#define EPFRAMEBUFFER_H

#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QMutex>
#include <QtCore/QObject>
#include <QtGui/QImage>

#include <atomic>
#include <mutex>

class EPFrameBuffer : public QObject
{
    Q_OBJECT

    // Testing results:
    // 0: ~780ms, initialize to white
    // 1: ~170ms, mono, no flashing
    // 2: ~460ms, 15 grayscale, flashing all pixels white -> black pixels
    // 3: ~460ms, 15, grayscale, flashing all pixels white -> black pixels
    // 4: ~460ms, 4 grayscale, flashing all pixels white -> black pixels
    // 5: ~460ms, 4 grayscale, flashing all pixels white -> black pixels
    // 6: ~135ms, no flashing
    // 7: ~300ms, white, 2 gray, 1 black, no flashing, stuck black?
    // 8: ~435ms, fast flashing, all gray, highlight, several grays, lowest color - 1 gets stuck
    // 9: ~2365ms, lots of flashing, delta something?

    enum Waveform {
        /** Display initialization
          * All -> white
          * 2000ms
          * ~780ms stall in driver
          * Supposedly low ghosting, high ghosting in practice.
          */
        INIT = 0,

        /**
          * Monochrome menu, text input, pen input
          * All -> black/white
          * 260ms to complete
          * 170ms stall in driver
          * Low ghosting
          */
        DU = 1,

        /** High quality images
          * All -> all
          * 480ms to complete
          * 460ms stall in driver
          * Very low ghosting
          */
        GC16 = 2,

        /** Text with white background
          * 16 -> 16
          * 480ms to complete
          * 460ms stall in driver
          * Medium ghosting
          *
          * Local update when white to white, Global update when 16 gray levels
          * For drawing anti-aliased text with reduced flash. This waveform makes full screen update
          * - the entire display except pixels staying in white will update as the new image is
          * written.
          */
        GL16 = 3,

        /** Text with white background
          * All -> all
          * 480ms to complete
          * 460ms stall in driver
          * Low ghosting
          *
          * Global Update
          * For drawing anti-aliased text with reduced flash and image artifacts (used in
          * conjunction with an image preprocessing algorithm, very little ghosting). Drawing time
          * is around 600ms. This waveform makes full screen update - all the pixels are updated or
          * cleared. Use this for anti-aliased text.
          */
        GLR16 = 4,

        /** Text and graphics with white background
          * All -> all
          * 480ms to complete
          * 460ms stall in driver
          * Low ghosting
          *
          * Global Update
          * For drawing anti-aliased text with reduced flash and image artifacts (used in
          * conjunction with an image preprocessing algorithm, very little ghosting) even more
          * compared to the GLR16 mode. Drawing time is around 600ms. This waveform makes full
          * screen update - all the pixels are updated or cleared. Use this for anti-aliased text.
          */
        GLD16 = 5,

        /** Fast page flipping at reduced contrast
          * [0, 29, 30, 31] -> [0, 30]
          * 120ms to complete
          * 135ms stall in driver
          * Medium ghosting
          *
          * Local Update
          * For drawing black and white 2-color images. This waveform supports transitions from and
          * to black or white only. It cannot be used to update to any graytone other than black or
          * white. Drawing time is around 120ms. This waveform makes partial screen update - it
          * updates only changed pixels. Image quality is reduced in exchange for the quicker
          * response time. This waveform can be used for fast updates and simple animation.
          */
        A2 = 6,

        /** Anti-aliased text in menus, touch and pen input
          * All -> [0, 10, 20, 30]
          * 290ms to complete
          * 300ms stall in driver
          *
          * No flashing, black seems to be stuck afterwards?
          */
        DU4 = 7,

        /** Unknown1
          * 435ms stall in driver
          *
          * Fast flashing, all gray, highlight?
          * Multiple grays
          * Next to lowest color gets stuck
          */
        UNKNOWN = 8,

        /** Init?
          * 2365ms stall in driver
          *
          * Lots of flashing, seems to do some delta updates (inverting unchanged?)
          */
        INIT2 = 9
    };

public:
    static EPFrameBuffer *instance();

    /// Which waveforms we use for different kinds of updates
    enum WaveformMode {
        Initialize = INIT,
        Mono = DU,
        Grayscale = GL16,
        HighQualityGrayscale = GC16,
        Highlight = UNKNOWN
    };

    enum UpdateMode {
        PartialUpdate = 0x0,
        FullUpdate = 0x1
    };

    static QImage *framebuffer() {
        return &instance()->m_fb;
    }

    Q_INVOKABLE static void setForceFull(bool force) { instance()->m_forceFull = force; }
    static bool isForceFull() { return instance()->m_forceFull; }

    int lastUpdateId() const { return m_lastUpdateId; }

    void setSuspended(bool suspended) { m_suspended = suspended; }
    bool isSuspended() const {
        std::lock_guard<std::mutex> locker(fbMutex);
        return m_suspended;
    }

    mutable std::mutex fbMutex;

    qint64 timeSinceLastUpdate() const;

public slots:
    static void clearScreen();
    static void sendUpdate(QRect rect, WaveformMode waveform, UpdateMode mode, bool sync = false);
    static void waitForLastUpdate();

private:
    EPFrameBuffer();
    QImage m_fb;
    QFile m_deviceFile;
    bool m_forceFull = false;
    bool m_suspended = false;
    int m_lastUpdateId = 0;

    std::mutex m_timerLock;
    QElapsedTimer m_lastUpdateTimer;
};

#endif // EPFRAMEBUFFER_H
NiLuJe commented 4 years ago

Okay, so I've updated the mappings according to that...

Which means we're unfortunately back to square one as far as A2 is concerned...

So, mildly intrigued how fbink -cfw && fbink -W A2 -i img.png fares (compared mainly to DU & REAGL).

On the vague chance the REAGL ones behave like on Kindle, you may need to make 'em flashing/FULL (-f) for them to behave properly. In which case, they won't behave very nicely when refreshing identical content, hence the full clear beforehand ;)...

tcrs commented 4 years ago

Okay, so I've updated the mappings according to that...

Which means we're unfortunately back to square one as far as A2 is concerned...

So, mildly intrigued how fbink -cfw && fbink -W A2 -i img.png fares (compared mainly to DU & REAGL).

On the vague chance the REAGL ones behave like on Kindle, you may need to make 'em flashing/FULL (-f) for them to behave properly. In which case, they won't behave very nicely when refreshing identical content, hence the full clear beforehand ;)...

I built fbink from master and tried ./fbink -cfw && ./fbink -W A2 -i fbink_image.png and ./fbink -cfw && ./fbink -W A2 -f -i fbink_image.png. Both do ~10s of disturbing flickering of the update area and then settle down to a (different but pretty poor) representation of the image (but using multiple gray shades). REAGL/REAGLD behave the same as A2 but with different image reproduction after settling (REGL seems to end up more or less inverted).

So no idea what that means!

NiLuJe commented 4 years ago

Huh. For reference, if I take my usual eInk dithering torture test, except in Grayscale:

Forma_Gray

That's roughly how I expect it to get rendered with DU or A2:

Forma_DU


Soo, I'm guessing a full recap is in order, with a test of every waveform mode, in order: DU, GC16, GL16 (which I expect to work properly, as far as crazy flashing is concerned ^^), and then REAGL, REAGLD, A2, DU4, UNKNOWN, INIT2.

I'm mainly concerned with identifying where the "actual" A2 behavior is hiding (if any).


FWIW, GC16 & GL16 should render something like the first picture here (i.e., full of banding).


CC @canselcik, because most of what was said in this PR might come in handy for libremarkable in one shape or form (also, more guinea pigs :D).

tcrs commented 4 years ago

OK, something funny is going on! I tested all the modes with

./fbink -fk && ./fbink -W MODE -i img.jpg

I took a load of pictures, which ended up with DU & REAGL looking like the example DU/A2 image you posted, GC16 & GL16 ended up banded grayscale. All the other modes did terrible flickering for 10s and settled into a banded randomly inverted image.

Then I thought I'd double check and ran the tests again. Now they all produce something which looks like GC16 without any crazy flickering. Am I doing something stupid in my testing here?

NiLuJe commented 4 years ago

I've sometimes seen weird things happening w/ A2 , but not to that extent ;).

That said, I'd check with the -w flag (on both sides): this ensures FBInk will block until the driver has completely finished dealing with the refresh, which should prevent the driver from deciding to merge a couple of refreshes together, which would ultimately affect the effective waveform selection ;). (Especially since -fk will default to GC16, and when merging updates, the waveform with the highest quality wins).

FWIW, REAGL behaving similarly to DU is consistent with the very first test you did when I originally asked about A2. (It also vaguely makes sense as it's the next ID after the properly identified modes (i.e., those used by xochitl)).

tcrs commented 4 years ago

Ah yes the -w option on the clear makes things consistent and match my first run. I think on the first run I was running the clear as a separate command (rather than linking them with &&) so there would have been a longer pause between the two. Makes sense now, mystery solved thanks!

Using ./fbink -fk -w && ./fbink -w -W MODE -i eink_test.png I get the results: DU& REAGL look like the example DU/A2 image you posted, GC16 & GL16 end up banded grayscale like the image you pointed to.

All the other modes have terrible flickering for 10s and settle into a banded randomly inverted image like this: flicker_modes and also timeout waiting for the update to complete.

NiLuJe commented 4 years ago

Whew, mystery solved ;).

Many thanks for the tests!

I'll tweak the mapping for this A2 trickery and update the documentation to strongly discourage anyone from trying other values, then, thanks!

Because, ouch, that's some weird output there :D.

hdhbdh commented 4 years ago

This fixes #40.