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

Update OLED driver to support some new displays #10379

Closed
wants to merge 3 commits into from

Conversation

sigprof
Copy link
Contributor

@sigprof sigprof commented Sep 20, 2020

Description

Update the OLED driver to make it work with more display variants:

Changes which needed to be made in the driver code:

  1. All of those displays need #define OLED_COLUMN_OFFSET 32, however, the existing driver code supported OLED_COLUMN_OFFSET only for OLED_IC_SH1106; the code for OLED_IC_SSD1306 needed to be updated to use the offset too.
  2. Address calculations in calc_bounds_90() were wrong, but they gave correct values for previously supported displays. The errors were uncovered when trying to configure the driver for the 64×48 display size — in this case the display width is no longer an integer multiple of the display height, and therefore blocks no longer occupy the whole height when using 90°/270° rotation, and the top and bottom page numbers in addressing commands must be calculated properly.
  3. While fixing the code, I also implemented the 90°/270° rotation support for OLED_IC_SH1106 — it gives a 20% to 50% performance penalty when testing on the 128×32 SSD1306 display (which actually supports both command sets), but this is still better than no rotation support at all.

Fixes from #10377 are also needed to make these displays work properly.

TODO before removing the draft status

  • Document OLED_COLUMN_OFFSET support for OLED_IC_SSD1306
  • Document rotation support for OLED_IC_SH1106
  • Figure out the appropriate location for example display configs and add configs for these displays there

Configuration for the 64×32 SSD1306 display

#define OLED_DISPLAY_CUSTOM
#define OLED_DISPLAY_WIDTH 64
#define OLED_DISPLAY_HEIGHT 32
#define OLED_COLUMN_OFFSET 32
#define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)
#define OLED_BLOCK_TYPE uint8_t
#define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8)
#define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
#define OLED_COM_PINS COM_PINS_ALT
#define OLED_SOURCE_MAP { 0, 8, 16, 24 }
#define OLED_TARGET_MAP { 24, 16, 8, 0 }

Configuration for the 64×48 SSD1306 display

#define OLED_DISPLAY_CUSTOM
#define OLED_DISPLAY_WIDTH 64
#define OLED_DISPLAY_HEIGHT 48
#define OLED_COLUMN_OFFSET 32
#define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)
#define OLED_BLOCK_TYPE uint32_t
#define OLED_BLOCK_COUNT 24
#define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
#define OLED_COM_PINS COM_PINS_ALT
#define OLED_SOURCE_MAP { 0, 8 }
#define OLED_TARGET_MAP { 8, 0 }

Configuration for the 64×128 SH1107 display

#define OLED_DISPLAY_CUSTOM
#define OLED_DISPLAY_WIDTH 64
#define OLED_DISPLAY_HEIGHT 128
#define OLED_COLUMN_OFFSET 32
#define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)
#define OLED_BLOCK_TYPE uint16_t
#define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 }
#define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 }
#define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8)
#define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
#define OLED_COM_PINS COM_PINS_ALT
#define OLED_IC OLED_IC_SH1106

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Keyboard (addition or update)
  • Keymap/layout/userspace (addition or update)
  • Documentation

Checklist

  • My code follows the code style of this project: C, Python
  • I have read the PR Checklist document and have made the appropriate changes.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

There are some 64×32 and 64×48 OLED displays with SSD1306-like
controllers that need the OLED_COLUMN_OFFSET feature (64 visible columns
are in the middle of the 128 columns supported by the controller).
Adding OLED_COLUMN_OFFSET to the column address makes these displays
usable with some restrictions (e.g., scrolling does not work properly,
because the uninitialized portions of display memory are scrolled into
view, and proper rotation needs further fixes).
Attempting to configure the OLED driver for a 64×48 display uncovered
some errors in the address calculations.  Other displays apparently
always used blocks that occupied the whole physical height with 90°/270°
rotation, but the 64×48 display requires using smaller blocks
(specifically, 24 blocks of 16 bytes, so that both height and width
could be divided into whole blocks), therefore the top and bottom page
numbers in the address need to be calculated properly.

There was also a minor error in the end page number calculation in
calc_bounds(), but it did not seem to affect anything (maybe that value
is not actually used by the controller unless blocks actually span
multiple pages).
Because the SH1106 controller does not support the horizontal addressing
mode, it is not possible to transfer the whole block at once when using
90°/270° rotation.  Implement this using separate transfers with address
setup for every page-wide strip instead; this is slower than doing a
single transfer, but still better than no rotation support at all.
@sigprof sigprof mentioned this pull request Sep 20, 2020
14 tasks
@drashna drashna added awaiting_pr Relies on another PR to be merged first bug core labels Sep 21, 2020
@drashna drashna requested a review from a team September 21, 2020 04:39
@sigprof
Copy link
Contributor Author

sigprof commented Sep 26, 2020

After some more testing it seems that the configuration for the 64×128 SH1107 display that I found is in fact wrong — I noticed that the right column was showing some garbage with low brightness; seems that the proper configuration involves changing the MULTIPLEX_RATIO and DISPLAY_OFFSET I2C command arguments, and the current driver does not offer a way to set these values from config.h.

@zvecr
Copy link
Member

zvecr commented Nov 7, 2020

Just FYI (also tagging @fauxpark), a quick test with a 64×128 SH1107 display no longer gives a clean black/white output with the default settings since the recent OLED brightness changes.

Kinda difficult to get an image, but
20201107_180509

Setting OLED_BRIGHTNESS less than 30, or reverting the 0x40 -> 0x20 change is enough to give a more pleasing output.

Also, awesome work on this PR. Was expecting to have to get these OLEDS working myself.

@sigprof
Copy link
Contributor Author

sigprof commented Jan 10, 2021

@zvecr Yes, the code for the 64×128 display (which actually uses the SH1107 chip, not SH1106) was wrong. Look at master...sigprof:oled-driver-new-hardware-support-v2 for now (I'm still rearranging those commits though).

The configuration for that 64×128 screen with the new code would be:

#define OLED_DISPLAY_CUSTOM
#define OLED_DISPLAY_WIDTH 64
#define OLED_DISPLAY_HEIGHT 128
#define OLED_COM_PIN_OFFSET 32
#define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)
#define OLED_BLOCK_TYPE uint16_t
#define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 }
#define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 }
#define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8)
#define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
#define OLED_COM_PINS COM_PINS_ALT
#define OLED_IC OLED_IC_SH1107

@fauxpark
Copy link
Member

The VCOMH deselect value might need to be chip-specific, then, or at least configurable.

@tzarc tzarc closed this Feb 27, 2021
@tzarc tzarc deleted the branch qmk:develop February 27, 2021 20:27
@tzarc
Copy link
Member

tzarc commented Feb 27, 2021

Sorry about that, GitHub decided to delete the develop branch from upstream when we merged it, despite being told otherwise. Reopened.

@tzarc tzarc reopened this Feb 27, 2021
@KarlK90
Copy link
Member

KarlK90 commented Apr 14, 2021

I've been using your implementation from the v2 branch since a couple of days without any problems, thank you!

The SH1107 Displays (link no longer works but I think it is this one) have very noticeable high pitched coil whine when lighting up large parts of the screen, setting PRE_CHARGE_PERIOD to 0x22 instead of 0xF1 fixes that problem to basically. This value is hard coded for all displays maybe this should be configurable as well?

@stale
Copy link

stale bot commented Jun 2, 2021

Thank you for your contribution!
This pull request has been automatically marked as stale because it has not had activity in the last 45 days. It will be closed in 30 days if no further activity occurs. Please feel free to give a status update now, or re-open when it's ready.
For maintainers: Please label with awaiting review, breaking_change, in progress, or on hold to prevent the issue from being re-flagged.

@mrninhvn
Copy link

Hi, is there any update on this?

@shawe
Copy link

shawe commented Jan 1, 2022

I'm trying the SSD1107 OLED from this link https://es.aliexpress.com/item/4000547865501.html?spm=a2g0o.9042311.0.0.a99263c0nuLi91 on a Lily58L, and seems to work fine but only with OLED_ROTATION_270 (at least works).

Can I help with any way to try to add better support?

@mrninhvn
Copy link

mrninhvn commented Jan 1, 2022

I'm trying the SSD1107 OLED from this link https://es.aliexpress.com/item/4000547865501.html?spm=a2g0o.9042311.0.0.a99263c0nuLi91 on a Lily58L, and seems to work fine but only with OLED_ROTATION_270 (at least works).

Can I help with any way to try to add better support?

#15238
Take a look.

@drashna
Copy link
Member

drashna commented Jan 1, 2022

Has some merge conflicts.

(Also, the sh1107 has a 128x128 display too)

@joh
Copy link
Contributor

joh commented Dec 2, 2022

Hi, is there any progress on this? Would love to see this merged :) FWIW the v2 branch seems to work fine on top of latest develop (after resolving some conflicts). Tested on these GME64128-02 modules.

@drashna drashna marked this pull request as ready for review December 11, 2022 20:35
@drashna drashna marked this pull request as draft December 12, 2022 04:33
@drashna
Copy link
Member

drashna commented Dec 12, 2022

drashna marked this pull request as ready for review [8 hours ago]

Not intentionally, at least.

Also, can also confirm that the v2 branch works well with the 128x128 SH1107 screens.

would like to get this or similar merged, partially because it's a pain to maintain a separate file

@drashna drashna mentioned this pull request Mar 10, 2023
14 tasks
@drashna
Copy link
Member

drashna commented May 11, 2023

Closing this since #20331 covers this, and some of the added suggestions

@drashna drashna closed this May 11, 2023
@drashna drashna mentioned this pull request May 28, 2023
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants