My Inky Phat clock - refresh speed question

Using the ideas put forward in Ben Krasnow’s YouTube video and other hacks, I’ve managed to get my InkyPhat to run with a refresh rate of around 1.5Hz, sufficient to display a clock updating every second. This only works when displaying just black and white pixels and, as mentioned already in this thread, risks degrading the display. (I run the clean.py script supplied with the Inky Python package periodically to minimise burn-in.)

The hacks I’ve been using are:

  1. A stripped-down LUT. After a bit of experimenting, I’ve found that this one gives pretty good results except perhaps for very thin white lines on a black background:

         'black': [
         # Phase 0     Phase 1     Phase 2     Phase 3     Phase 4     Phase 5     Phase 6
         # A B C D     A B C D     A B C D     A B C D     A B C D     A B C D     A B C D
         0b01010000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT0 - Black
         0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT1 - White
         0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # IGNORE
         0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT3 - Red
         0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT4 - VCOM
    
         # Duration            |  Repeat
         # A   B     C     D   |
        24,   24,    0,    0,     1,   # 0 Clear to black, then go to final voltage
         0,    0,    0,    0,     0,   # 1
         0,    0,    0,    0,     0,   # 2
         0,    0,    0,    0,     0,   # 3
         0,    0,    0,    0,     0,   # 4
         0,    0,    0,    0,     0,   # 5
         0,    0,    0,    0,     0,   # 6
         ],
    
  2. Since I know I’ll be updating the display constantly, there is no point powering down the display after an update operation. Keeping the display powered up also means that the display initialisation (including LUT loading) only needs to be performed once at startup.

  3. If the display is not being powered down after each update, it is more efficient to check that the display’s BUSY status has cleared before performing a screen update rather than waiting for BUSY to go low after each update. This frees up the application to work on preparing the next frame to be displayed in parallel with the display being updated.

  4. Since I only using black and and white pixels when doing continuous high-speed display refreshes, there is no need to write to the SSD1675A chip’s “RED” RAM every frame. This can be initialised with zeros just once at startup.

  5. I set the max SPI speed to 20MHz, not 488kHz. The SSD1675A can handle up to 20MHz and the PI’s SPI i/f up to 125MHz.

A more radical approach, which avoids flicker during the screen update and possibly reduces the burn-in risk, is to take a differential approach to updating, i.e. re-define the use of the LUT’s and SSD1675A’s display RAM as follows:

  • Set LUT0 to null
  • Set LUT1 to a sequence which turns a pixel known already to be black, to white
  • Set LUT2 to a sequence which turns a pixel known already to be white, to black
  • For pixels which are to be unchanged from one frame to the next, set their BW and RED RAM entries to 0 (so they use LUT0)
  • For pixels which are to be changed from black to white in the next frame, set their BW RAM entry to 1 and RED RAM entry to 0 (so they use LUT1)
  • For pixels which are to be changed from white to black in the next frame, set their BW RAM entry to 0 and RED RAM entry to 1 (so they use LUT2)