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

ILI9486 (Waveshare 3.5-inch (B)) support #136

Merged
merged 8 commits into from
Dec 12, 2020

Conversation

mattblovell
Copy link
Collaborator

@mattblovell mattblovell commented Dec 6, 2020

The following additions, primarily to device.py are working for me when using this ILI9486-based display:

https://www.waveshare.com/3.5inch-rpi-lcd-b.htm

attached directly to the GPIO header of an RPi4 Model B. That particular display (or the controller) wants to run in portrait mode, 320x480. Rotation is thus necessary to use it as 480x320. (I was stuck for quite a while getting an odd display trying to use it in landscape mode.)

The various demos within luma.examples all seem to be happy, using either full_frame or the diff algorithm to update the framebuffer. Some misc observations:

  • I've run the bounce.py demo with a SPI bus frequency up to 50 MHz, achieving ~23 fps. Performance does still scale with SPI bus frequency.

  • The pi_logo.py demo also runs at such high frequencies, but the rendered colors end up being incorrect. The leaves on the Pi logo end up being orange instead of green! Slowing down to 32 MHz gets the colors correct. (Animation speed is still quite good at that SPI frequency using the diff algorithm.)

  • Interestingly, the gradient example within colors.py is still unhappy even at 32 MHz. Even though the rest of that example, including the opening photo and the rainbow screen, all look fine, the gradient screen ends up with artifacts suggesting bad data transfer. Slowing down to 28 MHz, the gradient screen looks perfectly normal (photos below).

Thanks,
Matt

fixes #135

Gradient screen from colors.py @ 32 MHz

IMG-0715_gradient_32MHz

Gradient screen from colors.py @ 28 MHz

IMG-0716_gradient_28MHz

@mattblovell mattblovell mentioned this pull request Dec 6, 2020
@rm-hull
Copy link
Owner

rm-hull commented Dec 7, 2020

Nice!

Out of interest, have you tried the Linux framebuffer driver with this display?

To get this PR through we ought add some simple regression tests and update the documentation

@rm-hull
Copy link
Owner

rm-hull commented Dec 7, 2020

... and probably convert the CI from Travis to GitHub actions (in another PR) beforehand

@thijstriemstra
Copy link
Collaborator

... and probably convert the CI from Travis to GitHub actions (in another PR) beforehand

See #137

@mattblovell
Copy link
Collaborator Author

Out of interest, have you tried the Linux framebuffer driver with this display?

Yes, I first tried out the display via the repository that Waveshare provides:

https://github.com/waveshare/LCD-show.git

I didn't use their shell scripts, but inspected what overlay they make use of and loaded it myself. The dtoverlay uses a compatible string of ilitek,ili9486 with these addition parameters:

            waveshare35b@0 {
                compatible = "ilitek,ili9486";
                reg = <0x00000000>;
                pinctrl-names = "default";
                pinctrl-0 = <0x00000001>;
                spi-max-frequency = <0x00e4e1c0>;
                txbuflen = <0x00008000>;
                rotate = <0x0000005a>;
                bgr = <0x00000000>;
                fps = <0x0000001e>;
                buswidth = <0x00000008>;
                regwidth = <0x00000010>;
                reset-gpios = <0xffffffff 0x00000019 0x00000001>;
                dc-gpios = <0xffffffff 0x00000018 0x00000000>;

in addition to an array of init bytes. The spi-max-frequency above is 15 MHz. The overlay file looks to be identical to the GPL-licensed one at

https://github.com/TobiasVanDyk/RaspberryPi-GPIO-Displays/blob/master/ili9486/Waveshare/waveshare35b-v2.dts

(The relationship between that github repository and Waveshare's is unclear to me.)

The luma.examples work fine via linux_framebuffer, with bounce achieving >20 fps when using the diff algorithm. The combination of luma.core's diff algorithm with whatever approach the device driver is taking for updates leads to a fair amount of tearing. Using full_frame, bounce gets 6.2 fps through the framebuffer.

Using luma.lcd directly at 50 MHz (a frequency that is certainly questionable for this display), bounce is achieving 5.3 fps with full_frame and 19 to 23 fps with diff. There's much less tearing, though! :)

To get this PR through we ought add some simple regression tests and update the documentation

I'll take a look at what the tests require. Since the tests presumably run without actual display hardware, are they just performing some sanity checks? The ili9486 addition mimics the structure of the ili9341 support identically.

My chief concern is that other ili9486 displays may not have the 16-bit registers of the particular Waveshare that I have. Looking around github at other (open license) implementations for ili9486 support, the byte padding only gets mentioned in conjunction with Waveshare. That would seem straightforward to support -- use a conditional to control whether padding gets added or not -- but that conditional would be unique to the ili9486. I also have no means of HW testing it.

@mattblovell
Copy link
Collaborator Author

Any hints on how one runs tests? I'm still relatively new to Python development, and the amount of infrastructure around Python projects is impressive. That said, I don't know how to run much!

@thijstriemstra
Copy link
Collaborator

thijstriemstra commented Dec 8, 2020

@mattblovell from repo checkout directory:

make sure to install tox, pytest etc first using:

pip install -e .[test]

then run tests:

tox -e py37

or py38 or whatever version you're using.

also run:

tox -e qa

to check for any lint errors.

@thijstriemstra thijstriemstra changed the title Initial ILI9486 (Waveshare 3.5-inch (B)) support ILI9486 (Waveshare 3.5-inch (B)) support Dec 8, 2020
@rm-hull
Copy link
Owner

rm-hull commented Dec 8, 2020

I tend to develop luma code & run tests on a Mac or desktop Linux machine rather than on an RPi. It was often painfully slow - certainly on RPi 2B, but might be better now on 4B

@rm-hull
Copy link
Owner

rm-hull commented Dec 8, 2020

Also, I can help out with the tests. We can mostly do a cut’n’paste job from ili9341

@mattblovell
Copy link
Collaborator Author

Also, I can help out with the tests. We can mostly do a cut’n’paste job from ili9341

That would be most appreciated! I'll see if I can free up some time tonight to try out tox (per @thijstriemstra's reply above), but I don't necessarily know what I'm doing with the test infrastructure.

@mattblovell
Copy link
Collaborator Author

I double-checked that the padding zeros are indeed needed for the Column Address Set (0x2A) and Page Address Set (0x2B) commands within ili9486.display(). Removing any of the zero padding (either after the command or those in between any of the command's parameters) results in the diff_to_previous algorithm not getting drawn correctly on-screen.

"Armed" with that information, I thought I would reexamine the positive and negative gamma settings for ili9486 in both juh/fbcp-ili9341 and ImpulseAdventure/Waveshare_ILI9486. Adding the commands with byte pads just yields terrible colors -- blues and purples end up with really bad saturation.

Dumping the initialization bytes from the dtoverlay that Waveshare makes available and pulling the gamma correction from those, colors seem fine but don't appear noticeably different than what the display uses without any gamma controls specified.

The Waveshare overlay is using 18-bit colors, which matches the initialization I'm trying (via Memory Access Control, 0x36). The other two repositories are only set up for 16-bit colors. Perhaps that explains the difference.

Anyway, just thought I'd explore the gamma settings a bit further.

Starting on tests for ILI9486.  So far, test_init_320x480 is now passing.  Need to get tests_offsets and test_display_full_frame healthy.
@mattblovell
Copy link
Collaborator Author

I think I have the entries in test_ili9486.py working. I only have one screen size (full) supported.

tests/test_ili9486.py::test_init_320x480 PASSED                                                                    [ 56%]
tests/test_ili9486.py::test_init_invalid_dimensions PASSED                                                         [ 58%]
tests/test_ili9486.py::test_offsets PASSED                                                                         [ 60%]
tests/test_ili9486.py::test_contrast PASSED                                                                        [ 61%]
tests/test_ili9486.py::test_hide PASSED                                                                            [ 63%]
tests/test_ili9486.py::test_show PASSED                                                                            [ 64%]
tests/test_ili9486.py::test_display_full_frame PASSED                                                              [ 66%]

Execution time for tox -e py37 on an RPi4:

real    0m14.644s
user    0m9.499s
sys     0m1.141s

I don't immediately know why the Python 3.8 tests are unhappy.

@mattblovell
Copy link
Collaborator Author

mattblovell commented Dec 10, 2020

I don't immediately know why the Python 3.8 tests are unhappy.

Ah, linting woes. I like blank lines, though! :)

I'll try to clean that up...

Copy link
Owner

@rm-hull rm-hull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic!
I’ve got one of these on order now because of you! 😁

luma/lcd/device.py Show resolved Hide resolved
@rm-hull
Copy link
Owner

rm-hull commented Dec 11, 2020

FYI, you can run tox -e qa to run the PEP8 and documentation checks, and usually flake8 can be used to auto format (we should probably have a tox target that does this)

@mattblovell
Copy link
Collaborator Author

I’ve got one of these on order now because of you!

Excellent! Hopefully it even works! 😄

Did you get the Waveshare one or a different ILI9486-based one? I have to say that the IPS panel is a nice feature.

Copy link
Collaborator

@thijstriemstra thijstriemstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see comments. Can you also add yourself to CONTRIBUTING.rst?

luma/lcd/device.py Outdated Show resolved Hide resolved
tests/test_ili9486.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@thijstriemstra thijstriemstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks.

@rm-hull rm-hull merged commit 40ebe37 into rm-hull:master Dec 12, 2020
@mattblovell
Copy link
Collaborator Author

Great!

I'm very glad to contribute back to luma.lcd. The excellent documentation for this project, and the breadth of supported displays, is what encouraged me to give these little LCD displays a try in the first place. I've learned a lot since September.

@rm-hull
Copy link
Owner

rm-hull commented Dec 14, 2020

v2.8.0 released with this in 🚀 https://pypi.org/project/luma.lcd/2.8.0/

@mattblovell mattblovell deleted the dev/ili9486_support branch December 15, 2020 03:50
@Matthew1471
Copy link

16-bit

RE: 16-bit registers, I just found this : https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/tiny/ili9486.c#L38

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.

Support for ili9486
4 participants