Skip to content

Inky Impression 7.3 Does not Work As Expcted #105

@gsexton

Description

@gsexton

From @kedare

Hmm I could not make it work so far, I found a few issues so far:
Dev.Bounds() is always (0,0),(0,0), it's not properly set as it should automatically depending on the model (I had to force is via Opts.Height and Opts.Width)

    When Drawing, it would randomly fail with the following logs :

2025/03/02 19:22:47 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
2025/03/02 19:22:48 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
2025/03/02 19:22:48 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
2025/03/02 19:22:48 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor

Which apparently correspond to this : https://github.com/pimoroni/inky/issues/205
But on the python implementation this is not making the drawing fail, those are just warnings, it looks like on the Go implementation this stops the drawing (can't confirm as I can't draw at all)

    When not raising the previous error, it's not actually drawing anything, it does block however the code like if it was indeed drawing something (around 40s)

This is the code I am using: https://github.com/kedare/dashink/blob/main/pkg/hardware/host.go

Thanks

To Reproduce
Steps to reproduce the behavior:

  1. Modify the cmd/inky program call inky.NewImpression()
  2. Build the program and call with an appropriate image.

Output:

2025/03/02 19:22:47 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor

in my instrumented version, I get:

inky: GPIOLine(27).Out(): line_request chip_fd=7, ioctl: bad file descriptor.

Expected behavior
The program should render the image on the Display

Platform (please complete the following information):

  • OS: Raspbian Bookworm
  • Board Raspbery Pi 5 w/ 8GB
  • Device Inky Impression 7.3

Additional context

I changed the program to use the gpioioctl package directly since the impression file depends upon WaitForEdge(). The issue is coming in this function:

// Render renders the content of the [*DevImpression.Pix] to the screen.
func (d *DevImpression) Render() error {
	fmt.Println("In Render() Press Enter to begin render calls.")
	fmt.Scanln()
	if d.flipVertically {
		for w := 0; w < len(d.Pix)/2-1; w = w + d.width {
			for offset := 0; offset < d.width; offset++ {
				d.Pix[w+offset], d.Pix[len(d.Pix)-d.width-w+offset] = d.Pix[len(d.Pix)-d.width-w+offset], d.Pix[w+offset]
			}
		}
	}

	if d.flipHorizontally {
		for offset := 0; offset < len(d.Pix)-1; offset = offset + d.width {
			for i, j := 0, d.width-1; i < j; i, j = i+1, j-1 {
				d.Pix[i+offset], d.Pix[j+offset] = d.Pix[j+offset], d.Pix[i+offset]
			}
		}
	}
	log.Println("Preparing to create Merged(). Press Enter to Begin")
	fmt.Scanln()
	merged := make([]uint8, len(d.Pix)/2)

	log.Printf("len merged=%d\n Press Enter to continue", len(merged))

	fmt.Scanln()
	for i, offset := 0, 0; i < len(d.Pix)-1; i, offset = i+2, offset+1 {
		merged[offset] = (d.Pix[i]<<4)&0xF0 | d.Pix[i+1]&0x0F
		log.Printf("offset=%d", offset)
	}
	log.Println("Merged created.")
	log.Println("In Render() Press Enter to call Update()")
	fmt.Scanln()
	return d.update(merged)
}

When I run the Linux command lsof -p pid at the step Preparing to create Merged(). Press Enter to Begin, I see the following:

gsexton@raspberrypi:/proc/7019/fd $ ps xfa | grep main
  14698 pts/0    Sl+    0:00  |   \_ ./main -image /home/gsexton/George.png

gsexton@raspberrypi:/proc/7019/fd $ lsof -p 14698
COMMAND   PID    USER   FD      TYPE DEVICE SIZE/OFF   NODE NAME
main    14698 gsexton  cwd       DIR  179,2     4096 649617 /home/gsexton/periph/x/cmd/inky
main    14698 gsexton  rtd       DIR  179,2     4096      2 /
main    14698 gsexton  txt       REG  179,2  4169165 657764 /home/gsexton/periph/x/cmd/inky/main
main    14698 gsexton    0u      CHR  136,0      0t0      3 /dev/pts/0
main    14698 gsexton    1u      CHR  136,0      0t0      3 /dev/pts/0
main    14698 gsexton    2u      CHR  136,0      0t0      3 /dev/pts/0
main    14698 gsexton    3r      REG  179,2    20475  95166 /home/gsexton/George.png
main    14698 gsexton    4u  a_inode   0,14        0   1183 [eventpoll:5,6,7,8,9,10,11,12]
main    14698 gsexton    5u  a_inode   0,14        0   1183 [eventfd:191]
main    14698 gsexton    6r      CHR  254,0      0t0    132 /dev/gpiochip0
main    14698 gsexton    7r      CHR 254,10      0t0     88 /dev/gpiochip10
main    14698 gsexton    8r      CHR 254,11      0t0     89 /dev/gpiochip11
main    14698 gsexton    9r      CHR 254,12      0t0     90 /dev/gpiochip12
main    14698 gsexton   10r      CHR 254,13      0t0     91 /dev/gpiochip13
main    14698 gsexton   11r      CHR  254,0      0t0    132 /dev/gpiochip0
main    14698 gsexton   12w      REG   0,18    16384   3709 /sys/class/gpio/export
main    14698 gsexton   13u      CHR  153,1      0t0    665 /dev/spidev0.0

when I press enter, and this is executed:

	merged := make([]uint8, len(d.Pix)/2)
	log.Printf("len merged=%d\n Press Enter to continue", len(merged))
	fmt.Scanln()

the program output is:

2025/03/29 14:28:26 len merged=192000
 Press Enter to continue

running lsof -p again shows the expected gpiochip file handles open. Pressing ENTER to execute the code:

	for i, offset := 0, 0; i < len(d.Pix)-1; i, offset = i+2, offset+1 {
		merged[offset] = (d.Pix[i]<<4)&0xF0 | d.Pix[i+1]&0x0F
		log.Printf("offset=%d", offset)
	}
	log.Println("Merged created.")
	log.Println("In Render() Press Enter to call Update()")
	fmt.Scanln()

the output is:

2025/03/29 14:54:05 offset=191999
2025/03/29 14:54:05 Merged created.

and then re-running lsof -p shows:

gsexton@raspberrypi:/proc/7019/fd $ lsof -p 14698
COMMAND   PID    USER   FD      TYPE DEVICE SIZE/OFF   NODE NAME
main    14698 gsexton  cwd       DIR  179,2     4096 649617 /home/gsexton/periph/x/cmd/inky
main    14698 gsexton  rtd       DIR  179,2     4096      2 /
main    14698 gsexton  txt       REG  179,2  4169165 657764 /home/gsexton/periph/x/cmd/inky/main
main    14698 gsexton    0u      CHR  136,0      0t0      3 /dev/pts/0
main    14698 gsexton    1u      CHR  136,0      0t0      3 /dev/pts/0
main    14698 gsexton    2u      CHR  136,0      0t0      3 /dev/pts/0
main    14698 gsexton    3r      REG  179,2    20475  95166 /home/gsexton/George.png
main    14698 gsexton    4u  a_inode   0,14        0   1183 [eventpoll:5,12]
main    14698 gsexton    5u  a_inode   0,14        0   1183 [eventfd:191]
main    14698 gsexton   12w      REG   0,18    16384   3709 /sys/class/gpio/export
main    14698 gsexton   13u      CHR  153,1      0t0    665 /dev/spidev0.0

Note that the file descriptors to /dev/gpiochip* are gone. The error is being returned by cycleResetGPIO() because the Out() command is attempting to use the gpiochip0 file descriptor to perform an ioctl() for the pin:

func (d *DevImpression) cycleResetGPIO() error {
	if err := d.r.Out(gpio.Low); err != nil {
		return err
	}
	time.Sleep(100 * time.Millisecond)
	return d.r.Out(gpio.High)
}

The behavior isn't perfectly consistent. Sometimes creating the slice is enough to change the output of lsof, sometimes it isn't until the loop is done. It is not 100% consistent that it happens, but when it does, it's in one of those two spots.

The mainImpl() function has a reference to a gpioioctl.Chip[0],

I instrumented the GPIO chip to print when Close() is called, and that's not happening.

Also, I ran it under strace and don't see close calls with any of the affected file descriptors. On ArmV6, the ioctl error does not occur, but it just doesn't work. There are probably multiple issues.

@maruel Can you look at this? I'm stumped. It seems like either some sort of memory overwrite is happening, or something is garbage collecting things. I confirmed that the length of gpioioctl.Chips[0] is still well-constructed after the error happens, so it doesn't look like Init() is called twice making things strange.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions