support for ssd1107/sh1107
I recently bought a new OLED display on Aliexpress: https://www.aliexpress.com/item/4000547865501.html The antistatic bag was labelled SH1107. The display has a resolution of 64x128 (it is vertical). Datasheet is here: https://www.displayfuture.com/Display/datasheet/controller/SH1107.pdf I tried to use the luma.oled library for control, but failed. Can you please add support for this display as well? I can test. I tried to make some modifications in the library myself, but to no avail. For example, I tried to add a resolution of 64x128 to the SH1106 class (because some image, but shifted, could be achieved using this class), but failed. I didn't understand what the multiplex and displayoffset parameters were for.
Thanks.
In the end, I did it for my own needs myself. If anyone is interested, here is my new class SH1107:
class sh1107(device):
"""
Serial interface to a monochrome SH1107 OLED display.
On creation, an initialization sequence is pumped to the display
to properly configure it. Further control commands can then be called to
affect the brightness and other settings.
"""
def __init__(self, serial_interface=None, width=64, height=128, rotate=0, **kwargs):
super(sh1107, self).__init__(luma.oled.const.sh1107, serial_interface)
self.capabilities(width, height, rotate)
self._pages = self._h // 8
self._pagelen = self._w
settings = {
(64, 128): dict(multiplex=0x7F, displayoffset=0x60),
}.get((width, height))
if settings is None:
raise luma.core.error.DeviceDisplayModeError(
f"Unsupported display mode: {width} x {height}")
self.command(
self._const.DISPLAYOFF,
self._const.MEMORYMODE,
self._const.NORMALDISPLAY,
self._const.SETMULTIPLEX, settings['multiplex'],
self._const.DISPLAYALLON_RESUME,
self._const.SETDISPLAYOFFSET, settings['displayoffset'],
self._const.SETDISPLAYCLOCKDIV, 0x80,
self._const.SETPRECHARGE, 0x22,
self._const.SETCOMPINS, 0x12,
self._const.SETVCOMDETECT, 0x35,
)
self.contrast(0x7F)
self.clear()
self.show()
def display(self, image):
"""
Takes a 1-bit :py:mod:`PIL.Image` and dumps it to the SH1107
OLED display.
:param image: Image to display.
:type image: :py:mod:`PIL.Image`
"""
assert(image.mode == self.mode)
assert(image.size == self.size)
image = self.preprocess(image)
pixmap = image.load()
buf = bytearray(self._pagelen)
for page in range(self._pages):
for x in range(self._pagelen):
tmp = 0
for y in range(8):
tmp |= (pixmap[x, y + 8 * page] & 1) << y
buf[x] = tmp
self.command(0x10, 0x00, 0xb0 | page)
self.data(buf)
There are probably other resolutions than 64x128. However, I only have this one and therefore this new class does not allow you to select any other resolution.
thanks for sharing @Pako2
@rm-hull is this something worth including in luma.oled?
I bought a 0.78 inch SH1107 OLED (80x128) display that I'll test with your code @Pako2 when I find some time. It's a different screen than you linked but we'll see if it works.
I'll first give it a try with Arduino using something like https://github.com/adafruit/Adafruit_SH110x
I tested the 0.78 inch SH1107 OLED (80x128) documented in the comment above with your code @Pako2 and adjusted it for 80x128 by adding:
settings = {
(64, 128): dict(multiplex=0x7F, displayoffset=0x60),
(80, 128): dict(multiplex=0x7F, displayoffset=0x60),
}.get((width, height))
I have no idea what the values for multiplex or displayoffset should be though..
And using the following code:
serial = i2c(port=1, address=0x3C)
device = sh1107(serial, width=80, height=128, rotate=0)
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline="white", fill="black")
draw.text((30, 40), "Hello World", fill="white")
sleep(40)
produces this image on the screen:

Adding rotate=1:
device = sh1107(serial, width=80, height=128, rotate=1)
produces this image:

Any idea how to get it to properly render?
I would try experimenting with the multiplex and displayoffset parameters. For example like this:
settings = {
(64, 128): dict(multiplex=0x7F, displayoffset=0x60),
(80, 128): dict(multiplex=0x4F, displayoffset=0x68),
}.get((width, height))
I am based on this source: u8x8_d_sh1107.c
thanks @Pako2, that worked!
With rotate=0 (default):

With rotate=1:

Would you be willing to make a pull request @Pako2? I can copy your code and make one as well, just let me know.
nice work .. I was about to suggest trying tweaking the display offset 😁
Would you be willing to make a pull request @Pako2? I can copy your code and make one as well, just let me know.
Hi. I am glad that my code works and that it can be used to complement such a great library. And I also prefer if I don't have to make another PR. Please do it yourself.
Sounds good @Pako2, I've opened #359