robert-hh / SH1106

MicroPython driver for the SH1106 OLED controller
Other
163 stars 38 forks source link

When the screen is rotated by 90 degrees the partial updates are not working properly #26

Closed peter-l5 closed 2 years ago

peter-l5 commented 2 years ago

Partial updates do not work properly when the screen is rotated by 90 degrees. in normal orientation the display can be written in horizontal pages, 8 pixels high. if the framebuffer is effective rotated by 90 degrees by using colour mode: MONO_HMSB, then writing pages to the display writes vertical stripes of 8 pixels rather than horizontal ones. As a result partial updates for a rotated display do not work properly. It is possible to fix this by changing the display's memory addressing mode to vertical addressing and writing 1 row at a time. I have written some code that implements this for the similar SH1107 display driver IC and will post it in the coming days.

CRImier commented 2 years ago

ah nice! this isn't something I've seen people do, but having this be supported would indeed be lovely!

(for you or anyone who's reading this, you can disable partial updates by calling .show(full_update=True) if they're causing problems and you'd rather not dig deeper)

peter-l5 commented 2 years ago

I have placed some code that tackles this here: https://github.com/peter-l5/SH1107 There are quite a number of other changes in the code that speed it up slightly, at least according to my testing. Unfortunately I think I have probably broken the SPI interface. Any comments or suggestions welcome. PS I'm pretty new to github so apologies if I'm breaking any conventions

peter-l5 commented 2 years ago

The changes include setting the I2C interface to run at 1MHz, which seems to work OK. At this bus speed, full screen update takes about 33ms in normal orientation and about 58ms rotated by 90 degrees.

robert-hh commented 2 years ago

The common style is NOT to change the interface properties in a driver that uses it. Interface setting should be left to the code calling it. In that case, the I2C object has to be created by the code using the SH1107 driver. Therefore it can be created as needed. The same applies to SPI.

peter-l5 commented 2 years ago

@robert-hh : thanks. My SH1107 driver is functional but still includes test code. The I2C frequency is set in the test code rather than the driver itself, which still allows the user of the driver to use an I2C object with a frequency property of their choice. That seems consistent with your style recommendation as far as I know, but I could be missing something. I'd be happy to propose a fix via pull request for this issue in the SH1106 driver based on the code I've written for the SH1107, although it might take 2-3 weeks.

peter-l5 commented 2 years ago

@robert-hh, all, I wanted to put for some options for addressing this issue:

  1. A possibility - as discussed above - would be to bring in the changes that I have made in this SH1107 driver, changing the screen addressing mode and write horizontal rows to the screen, instead of vertical pages. This does assumes that the SH1106 has essentially the same commands as the SH1107, which I have not checked. And as I don't have a SH1106 display I haven't been able to demostrate the problem. Instead I assume it is a problem by analogy with the operation of the FrameBuffer class and my SH1107 driver variant. On the plus side In speed terms for a full-update the way I have written seems 10-15% faster for a full-update - as while writing rows is slower overall than pages (ie 8 row blocks), it isn't necessary to reshape a copy of the FrameBuffer (that also saves the memory needed for a copy of the FrameBuffer). But a not totally insignificant challenge with this approach is that I have made quite a number of other changes to the code that would make it slightly fiddly to move across (not to mention that I don't have a SH1106 display for testing and would need one in order to be able to confidently propose a fix.
  2. Another option would be to change the update registering so that in 90 or 270 degree rotated mode, it registers vertical bands rather than horizontal stripes. This would be alighted with the FrameBuffer and writing to the display in pages, however vertical bands are probably not very useful as a partial update mechanism for most applications of such displays. This would also add quite a bit of complexity and length to the code. (which wouldn't aesthetically fit well with it's current concise style, I would mention.)
  3. The final option would be to turn off the partial updates in the code when the screen has 90 or 270 degree orientation. As no-one has raised this problem as an issue before, perhaps this would be a practical and low effort way forward for the time being at least.

My suggestion would be to go with option 3 for the time-being. It does render the display slower when only a partial update is needed. But on the plus side, it fixes the problem for users of the driver and is low effort coding-wise.