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

Port to gpiod for Bookworm/Pi 5 and beyond #182

Merged
merged 27 commits into from
Sep 11, 2024
Merged

Port to gpiod for Bookworm/Pi 5 and beyond #182

merged 27 commits into from
Sep 11, 2024

Conversation

Gadgetoid
Copy link
Member

@Gadgetoid Gadgetoid commented Nov 21, 2023

Hey ho, we're in the process of transitioning the Inky library and examples to gpiod, virtual environments and the shiny new Pi 5.

As such, I'd really like your feedback!

Progress

  • inky - old 2nd generation, 2/3-colour Inky pHAT boards and wHAT boards - (yellow) pHAT works, other untested
  • inky_ssd1608 - newer Inky pHAT boards based on the SSD1608 - (red) pHAT works, others untested
  • inky_ssd1683 - newer Inky wHAT boards - 🎉 seems to work for me on my Pi 5. (SEE BELOW)
  • inky_uc8159 - Inky Impressions 4 - it works! (SEE BELOW)
  • inky_uc8159 - Inky Impressions 5.7" - it works! (SEE BELOW)
  • inky_ac073tc1a - Inky Impressions 7.3" - It works!

Note: Most examples using GPIO have not been ported, with the exception of examples/7color/buttons.py.

Note: The simulator might be broken. I am removing conditional imports and custom ImportError trapping where I can, since this overcomplicates the codebase especially when we try to move to gpiod.

👉 Installation Instructions 👈

Grab this branch and install with the --unstable (local downloaded copy of the library) flag:

git clone https://github.com/pimoroni/inky -b gpiod
cd inky
./install.sh --unstable

A venv should be created for you, though this step will be skipped if you're already inside one (in theory).

If you get errors, make sure you activate that virtual environment. Your bash prompt should start with (pimoroni):

source ~/.virtualenvs/pimoroni/bin/activate

The installer should have added some new lines to /boot/firmware/config.txt so that SPI gets out of the way of the chip-select pin and the EEPROM i2c is enabled (for detecting your Inky board type)-

dtoverlay=spi0-0cs
dtoverlay=i2c1
dtoverlay=i2c1-pi5

Reboot your Pi, and see if anything breaks.

Things to look out for:

  1. Any errors writing /boot/firmware/config.txt and that the lines mentioned above are present
  2. Make sure /boot/config.txt is still a symlink to /boot/firmware/config.txt - I think sed breaks this horribly (Note: On my Pi it now seems like this is not a symlink on purpose?)
  3. Examples and such are copied to ~/Pimoroni
  4. No missing packages or heinous compile steps during install
  5. Your product actually works!

Inky wHAT (ssd1683)

Tested before the dtoverlay=spi0-0cs change, which worked, but this broke SSD1683 because it was using the default SPI chip-select behaviour. I have migrated everything over to use soft chip-select, though it might be worth seeing if we can give it over to the SPI driver on all counts and avoid needing to load that overlay.

Inky Impressions 5.7"

I've been having trouble with this, and I'm still suspicious but it seems to now be working-

PYTHONPATH=../../ python3 image.py --type 7colour --file images/inky-4.0-redchain.jpg

I have a test board with no EEPROM data, so it blurts out:

Detected None
Failed to detect an Inky board. Trying --type/--colour arguments instead...

/home/phil/Development/pi/inky/inky/inky_uc8159.py:242: UserWarning: SPI: Cannot disable chip-select!
  warnings.warn("SPI: Cannot disable chip-select!")
/home/phil/Development/pi/inky/inky/inky_uc8159.py:337: UserWarning: Busy Wait: Held high. Waiting for 1.00s
  warnings.warn(f"Busy Wait: Held high. Waiting for {timeout:0.2f}s")
/home/phil/Development/pi/inky/inky/inky_uc8159.py:337: UserWarning: Busy Wait: Held high. Waiting for 0.20s
  warnings.warn(f"Busy Wait: Held high. Waiting for {timeout:0.2f}s")
/home/phil/Development/pi/inky/inky/inky_uc8159.py:337: UserWarning: Busy Wait: Held high. Waiting for 32.00s
  warnings.warn(f"Busy Wait: Held high. Waiting for {timeout:0.2f}s")

This may have been another SPI chip-select issue.

Inky Impressions 4"

My 4" proto has no EEPROM data flashed, so I modified stripes.py as follows:

#!/usr/bin/env python3

# To simulate:
# from inky.mock import InkyMockImpression as Inky
#from inky.auto import auto
from inky.inky_uc8159 import Inky

#inky = auto(ask_user=True, verbose=True)
inky = Inky((640, 400))

for y in range(inky.height - 1):
    color = y // (inky.height // 7)
    for x in range(inky.width - 1):
        inky.set_pixel(x, y, color * 0x11)

inky.show()
# To simulate:
# inky.wait_for_window_close()

* Fix VENV_DIR path.
* Fix auto_venv.sh creation.
* install.sh: normalise whitespace.
* install.sh: rework for better error reporting and fix some bugs.
* README.md: Correct coveralls badge branch.
* CI: Update GitHub Actions versions.
* QA: Add shellcheck and fix/ignore all issues.
* install.sh: slightly better feedback for setup commands.
* install.sh: fix quoting bug in do_config_backup.
* install.sh: don't output printf commands.
GPIO setup tests have been pruned and could use rewriting.
PIL is now always assumed to be installed.
@stonehippo
Copy link

@Gadgetoid here's the output:

No display EEPROM detected,
you might have an old Inky board that doesn't have an EEPROM - eg: early Inky pHAT boards.

Try running examples with --colour <black/red/yellow>

Or writing your code using:

from inky.phat import InkyPHAT

display = InkyPHAT("<black/red/yellow>")

Checking the back of the board, there's no EEPROM. I've been using --type what --colour red with the other scripts.

I've also got an old school yellow PHAT that works as expected, so that's cool.

@stonehippo
Copy link

Tried --type whatssd1683 just to see what would happen. Answer: nothing at all.

@stonehippo
Copy link

stonehippo commented Apr 7, 2024

@Gadgetoid Ok, interesting. I created an instance of InkyWHAT in the REPL and I can draw boxes correctly with .set_pixel without any issues. I've tried loading the what logo image with .set_image and things go off the rails. Which lead me to look at .set_image, which seems to be broken. Here's the implementation in the gpiod branch:


    def set_image(self, image):
        """Copy an image to the buffer.
        """
        image = image.resize((self.width, self.height))

        if not image.mode == "P":
            palette_image = Image.new("P", (1, 1))
            r, g, b = 0, 0, 0
            if self.colour == "red":
                r = 255
            if self.colour == "yellow":
                r = g = 255
            palette_image.putpalette([255, 255, 255, 0, 0, 0, r, g, b] + [0, 0, 0] * 252)
            image.load()
            image = image.im.convert("P", True, palette_image.im)

        canvas = Image.new("P", (self.rows, self.cols))
        width, height = image.size
        canvas.paste(image, (0, 0, width, height))
        self.buf = numpy.array(canvas, dtype=numpy.uint8).reshape((self.cols, self.rows))

That's all good, until it hits the new canvas. It looks like self.rows and self.cols are swapped. On the wHAT, this creates a canvas of (300,400) instead of (400, 300), which then gets the existing image pasted into it. That distorted image then gets put in the buffer.

To confirm that was the issue, I swapped self.rows and self.cols:

canvas = Image.new("P", (self.cols, self.rows))

The result:
IMG_3012

IMG_3014

I haven't looked into whether this change breaks things on my pHAT or not yet. Frankly, it's a little weird to me that it's working anywhere.

@Gadgetoid
Copy link
Member Author

I haven't looked into whether this change breaks things on my pHAT or not yet. Frankly, it's a little weird to me that it's working anywhere.

Looks like I updated this code as part of this branch, but it's as of yet untested.

I would expect it to break the pHAT if it was using the same driver. It may be that the cols/rows values for the displays need updating and the code tweaked to use them properly. Very much something I need to write a test for!

@stonehippo
Copy link

Yeah, you might not really need cols/rows at all (except maybe for backward compatibility with early versions). It looks like they're just the same values as the width and height for all displays?

@Gadgetoid
Copy link
Member Author

Assuming the test tests what I think it does - I'm pretty rusty on these old Inky boards - then just removing the additional canvas and image pasting step seems to work. Afaik this step does nothing at best, since the image is already resized to the display width/height. Raised the new test and possible fix and a PR against this branch here: #188

@BryanH
Copy link

BryanH commented Apr 29, 2024

@Gadgetoid

Make sure /boot/config.txt is still a symlink to /boot/firmware/config.txt

It isn't.

Here's the identify for my board:

Found: Yellow wHAT
Display: 400x300
Color: yellow
PCB Variant: 1.2
Display Variant: 2
Time: b'2023-02-01 09:29:03.0'

When I run the logo example following the above installation instructions, I get:

$ python3 logo.py

Inky pHAT/wHAT: Logo

Displays the Inky pHAT/wHAT logo.


Detected Yellow wHAT
/home/pi/.virtualenvs/pimoroni/lib/python3.11/site-packages/inky/inky.py:254: UserWarning: SPI: Cannot disable chip-select!
  warnings.warn("SPI: Cannot disable chip-select!")

My Inky shows the same display as in the comment by @stonehippo (although mine is yellow).

@Gadgetoid
Copy link
Member Author

It isn't.

Yeah, they changed that recently-ish just to keep me on my toes 😢

In that case, what's in your /boot/firmware/config.txt?

@BryanH
Copy link

BryanH commented May 3, 2024

@Gadgetoid Here you go!

# For more options and information see
# http://rptl.io/configtxt
# Some settings may impact device functionality. See link above for details

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
dtparam=spi=on

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

# Additional overlays and parameters are documented
# /boot/firmware/overlays/README

# Automatically load overlays for detected cameras
camera_auto_detect=1

# Automatically load overlays for detected DSI displays
display_auto_detect=1

# Automatically load initramfs files, if found
auto_initramfs=1

# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
max_framebuffers=2

# Don't have the firmware create an initial video= setting in cmdline.txt.
# Use the kernel's default instead.
disable_fw_kms_setup=1

# Run in 64-bit mode
arm_64bit=1

# Disable compensation for displays with overscan
disable_overscan=1

# Run as fast as firmware / board allows
arm_boost=1

[cm4]
# Enable host mode on the 2711 built-in XHCI USB controller.
# This line should be removed if the legacy DWC2 controller is required
# (e.g. for USB device mode) or if USB support is not required.
otg_mode=1

[all]

dtoverlay=i2c1
dtoverlay=i2c1-pi5
dtoverlay=spi0-0cs

@Gadgetoid
Copy link
Member Author

Looks like I need a try/catch around the chip select disable call- since it isn’t owned by the SPI driver 😬

@Gadgetoid
Copy link
Member Author

Gadgetoid commented May 7, 2024

Oh hmm, wait, this warning is the result of such a try/catch.

Sorry I have completely lost the plot from juggling so much stuff that my memory was purged of any and all recollection of this issue.

More discussion and a potential fix should be detailed here. I'll get some install instructions added for the fix branch so it's easier for you to try - #188

@davidskeck
Copy link
Contributor

Hello, I tried installing this branch with the given instructions on the Pi 5, but I get the below error. Any ideas?

  Building wheel for spidev (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for spidev (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [27 lines of output]
      /tmp/pip-build-env-cogozc2i/overlay/lib/python3.11/site-packages/setuptools/dist.py:447: SetuptoolsDeprecationWarning: Invalid dash-separated options
      !!
      
              ********************************************************************************
              Usage of dash-separated 'description-file' will not be supported in future
              versions. Please use the underscore name 'description_file' instead.
      
              By 2024-Sep-26, you need to update your project and remove deprecated calls
              or your builds will no longer be supported.
      
              See https://setuptools.pypa.io/en/latest/userguide/declarative_config.html for details.
              ********************************************************************************
      
      !!
        opt = self.warn_dash_deprecation(opt, section)
      running bdist_wheel
      running build
      running build_ext
      building 'spidev' extension
      creating build
      creating build/temp.linux-aarch64-cpython-311
      aarch64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/home/david/pinky/.venv/include -I/usr/include/python3.11 -c spidev_module.c -o build/temp.linux-aarch64-cpython-311/spidev_module.o
      spidev_module.c:28:10: fatal error: Python.h: No such file or directory
         28 | #include <Python.h>
            |          ^~~~~~~~~~
      compilation terminated.
      error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for spidev
Successfully built inky
Failed to build spidev
ERROR: Could not build wheels for spidev, which is required to install pyproject.toml-based projects
⚠ WARNING: ^^^ 😬 previous command did not exit cleanly!
Done!


@davidskeck
Copy link
Contributor

Hello, I tried installing this branch with the given instructions on the Pi 5, but I get the below error. Any ideas?

  Building wheel for spidev (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for spidev (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [27 lines of output]
      /tmp/pip-build-env-cogozc2i/overlay/lib/python3.11/site-packages/setuptools/dist.py:447: SetuptoolsDeprecationWarning: Invalid dash-separated options
      !!
      
              ********************************************************************************
              Usage of dash-separated 'description-file' will not be supported in future
              versions. Please use the underscore name 'description_file' instead.
      
              By 2024-Sep-26, you need to update your project and remove deprecated calls
              or your builds will no longer be supported.
      
              See https://setuptools.pypa.io/en/latest/userguide/declarative_config.html for details.
              ********************************************************************************
      
      !!
        opt = self.warn_dash_deprecation(opt, section)
      running bdist_wheel
      running build
      running build_ext
      building 'spidev' extension
      creating build
      creating build/temp.linux-aarch64-cpython-311
      aarch64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/home/david/pinky/.venv/include -I/usr/include/python3.11 -c spidev_module.c -o build/temp.linux-aarch64-cpython-311/spidev_module.o
      spidev_module.c:28:10: fatal error: Python.h: No such file or directory
         28 | #include <Python.h>
            |          ^~~~~~~~~~
      compilation terminated.
      error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for spidev
Successfully built inky
Failed to build spidev
ERROR: Could not build wheels for spidev, which is required to install pyproject.toml-based projects
⚠ WARNING: ^^^ 😬 previous command did not exit cleanly!
Done!

aaand it looks like this fixes it... sudo apt-get install python3-dev

@davidskeck
Copy link
Contributor

image
any ideas on this one?

Gadgetoid and others added 3 commits September 6, 2024 14:49
The image is resized to the display width/height, what was this even for?
@Gadgetoid Gadgetoid merged commit b86f686 into main Sep 11, 2024
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants