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

Compiling touchscreen driver for PINN #15

Closed
procount opened this issue Jan 4, 2019 · 21 comments
Closed

Compiling touchscreen driver for PINN #15

procount opened this issue Jan 4, 2019 · 21 comments

Comments

@procount
Copy link

procount commented Jan 4, 2019

I already got the hyperpixel 3.2 and Hyperpixel 4 displays working with PINN,
I still haven't converted the touchscreen driver for 3.2 but I noticed the hyperpixel 4 used a more standard Goodix driver so I thought I'd try that.

I recompiled the overlay on Raspbian to allow 180 degree rotation. I copied this to PINN's overlays folder, but I'm not sure any dtparam rotation settings actually work as I have to add display_rotate=1|3
I added the Goodix driver to buildroot, along with i2c support and i2c GPIO bitbanging for the i2c-3 pins.

Now I have a working touchscreen mouse, BUT the scaling seems to be reversed. So instead of it thinking the display is 800x480, it thinks it is 480x800. In one direction it moves too slowly and doesn't cover the display, and in the other dimension it moves t0o quickly and shoots off the bottom of the screen. Any idea what I am missing to reverse the scaling, because it works ok in Raspbian?

@Gadgetoid
Copy link
Member

This is- surprisingly -how the touchscreen behaves in Raspbian, too, except X or uinput, or whatever is latching onto the touchscreen and serving as the input driver (honestly I'm keeping track of so much software at this point that my brain is an information FIFO) seems to quite effectively disguise this fact and scales the touchscreen axes so that they work.

I'm not sure what the fix for this would be in the context of PINN since I don't know how it handles input, but you may need to drop a config file somewhere explicitly setting the screen resolution and touch resolution scales.

An alternative may be to use the out-of-tree Goodix driver from here - https://github.com/pimoroni/HyperPixel4TouchScreen/tree/master/driver

It's based on the gt9xx driver created by Goodix. It supports some features the upstream driver does not, and as such supports all 4 rotations and - if I remember correctly - has the X and Y axis the correct way around.

@procount
Copy link
Author

procount commented Jan 8, 2019

Thanks. I was not aware of that driver so I will try it instead.

@procount
Copy link
Author

procount commented Jan 8, 2019

I tell a lie, I had seen it, but thought it was the same as the kernel version - wrong!
I tried this out-of-tree version and got different results, but still not correct.
I think I have figured out what is wrong, though.
It seems to me that by default, this touchscreen driver is operating in portrait mode, not landscape as I imagined. So it's concept of X and Y seem to be reversed. I played about with the DTS files and with the rotate_1 setting, I had to set touchscreen-size-x=480 and touchscreen-size-y=800, which seems a bit contrary! Maybe this is why you see the same effect in Raspbian?

But anyway, it seems to be working now! I just need to adapt it for the other rotations.

It would be nice to somehow detect which of the hyperpixel 3.2, 4.0 or RPF 7" touchscreens are fitted and setup PINN accordingly. I have seen the other thread about switching between hyperpixel and HDMI, but I think it would need further work to set up the specific touchscreens.

@procount
Copy link
Author

procount commented Jan 8, 2019

I can't get the hyperpixel4 overlay to process any parameters, so I modified the DTS file as follows to get it to work in rotate_1 and rotate_3:

    /* display_lcd_rotate=3 */
    /* Landscape, USB ports on right */
    fragment@7 {
        target = <&ft6236>;
        __overlay__ {
            touchscreen-swapped-x-y;
            touchscreen-inverted-x;
            touchscreen-inverted-y;
            touchscreen-size-x = <480>;
            touchscreen-size-y = <800>;
        };
    };
    /* display_lcd_rotate=1 */
    /* Landscape, USB ports on left */
    fragment@8 {
        target = <&ft6236>;
        __dormant__ {
            touchscreen-swapped-x-y;
            touchscreen-size-x = <480>;
            touchscreen-size-y = <800>;
        };
    };

Edit: Hmm, but the problem with this is that it screws up Raspbian X windows. Ho hum

@procount
Copy link
Author

Comparing the hdmi_timings for hyperpixel and hyperpixel4, it does appear that the hyperpixel4's default orientation is portrait, whereas the hyperpixel3.2 is landscape. Hence the need to rotate HP4 by 1 and 3, and the HP3.2 by 0 and 2. I assume this is reflected in the touchscreen orientation too.

I also haven't a clue how Raspbian's X windows system knows that it has to rotate HP4. For now I shall just live with a separate driver and DTS file to get it working with PINN.

@Gadgetoid
Copy link
Member

I'll have to join you in the having no clue club- how X windows figures out the touchscreen is a total mystery to me. I'm just glad it works!

Detecting HyperPixel 4 should be possible by querying the i2c device, but I'm not sure how you might detect the official display since it uses the other i2c bus.

@Gadgetoid
Copy link
Member

I've ported hyperpixel4-init over to libgpiod which may be of use to you- https://github.com/pimoroni/hyperpixel4/blob/pi4-libgpiod/src/hyperpixel4-init.c

On the Pi 4 I had migrated to Python again, since libbcm2835 wasn't Pi4-compatible for a while. The switch to libgpiod should be more generic and, with any luck, maintain support with future board releases.

I am, of course, assuming that a libgpiod-based binary will work at all in an initramfs or in the cut down envinronment that PINN uses for its menu. I'm not 100% sure if this is the case.

@procount
Copy link
Author

Thanks for keeping me informed. I will take a look.
I need to look at my driver soon anyway, as I have a small problem of the Hyperpixel4 blanking when I touch a particular part of its touchscreen... very odd behaviour!

@Gadgetoid
Copy link
Member

I'm not sure if it's relevant to your adventures, but I've just merged a suite of fixes/improvements to the HyperPixel4/Pi3B support branch - https://github.com/pimoroni/hyperpixel4/pull/37/files

New install/usage instructions are here: https://github.com/pimoroni/hyperpixel4/tree/pi3

@procount
Copy link
Author

Cheers, Phil.

@procount
Copy link
Author

procount commented Nov 28, 2019

@Gadgetoid -In attempting to fix my random display blanking (which was due to some unhandled interrupt) I have separated my kernel driver into 2 drivers now - one to initialise the LCD display, and one for the touch interface. So far, no more blanking (yet!)

I also made my dts overlay compatible with the Pi4 and earlier models, so no need for separate Pi3/Pi4 implementations.

(EDIT: I thought it had started working on address 0x14 for both pi3 and pi4, but I think it was due to me scrolling the console instead of using the keys when using 'less' and viewing out of date messages. :doh: )

But do you know why/how it can change from address 0x5d to 0x14 when moving from a pi3 to a pi4?

@Gadgetoid
Copy link
Member

I haven't been able to identify exactly what the cause of the 0x5d to 0x14 address change is- it's clearly some characteristic of the address select functionality (and lack of onboard hardware pull resistor on our part), combined with a race condition or slight variation in how the GPIO pins are brought online on the Pi 4 versus Pi 3. There is no fix short of supporting both addresses and you can't even rely on the Pi 4 getting a specific address since variations in the temperature of the HyperPixel 4 (or Pi) are sufficient enough to alter the race condition and change the address.

My findings, and my own software fix, are available here- #41 (comment)

Long story short- I needed a .dtbo file for each address, plus one for the common stuff.

7520346

@procount
Copy link
Author

procount commented Dec 3, 2019

I know it's not exactly the same, but in the 911 data sheet p10 (https://www.crystalfontz.com/controllers/GOODIX/GT911/) it talks about changing the address based on the timing of the int and reset lines, so I guess it explains your solution.

I combined all dtbs into 1 file instead of 3 separate ones.

I'm putting my init & touchscreen kernel drivers back together again since (I think 🤞 ) I found my blanking issue, and since the INT pin is shared between the LCD and the touchscreen, it doesn't make sense to separate the drivers. Plus it seems to cause problems on the pi4.

I'm just having a problem stitching it all back together again, but I hope to have a single kernel driver and single dtbo file for pi3 & pi4 soon.

@procount
Copy link
Author

procount commented Dec 3, 2019

Oh, and the lack of GPIO pins to add the reset line prevents the goodix driver from setting the address to 0x14 or 0x5d in the _reset() function, so it just depends on the state of the pins. I think some of the pull resistors have changed from pi3 to pi4 also, so maybe that is contributory? 🤷‍♂

@mikekscholz
Copy link

I just compared the the gpio tables for the 3b and 4 and it looks like all of the external pull resistors are still the same.

@procount
Copy link
Author

procount commented Dec 3, 2019

OK thanks. It was just a hunch.

One more thing - my Hyperpixel4 is obviously an earlier version, since it only has 4 pins on the I2C breakout connector, so no INT pin.

@mikekscholz
Copy link

Wait the new ones have 5?! Ive been trying to figure out what would happen if I wired up my trackball and connected its interrupt to the touchscreen interrupt but noones ever replied to my question if it would be safe or not to try.

@procount
Copy link
Author

procount commented Dec 3, 2019

Apparently, if you look at the photo in #41 (comment)

Sorry, I've not seen your post.
But with my LIMITED understanding of all this, it should be possible for device drivers to share IRQs. The kernel should just call each device driver in turn. it's up to the device drivers to decide if the interrupt was meant for it. In the case of the touchscreen driver, it will just read and process any events that are present (or not). Your trackball would probably do the same.
Note the INT pin is also used as an SPI CLK pin on the hyperpixel to initialise the LCD.

@mikekscholz
Copy link

I could be catastrophically wrong but I assumed that the interrupt pin once booted would be how click events on the screen were sent and if true then they might be indistinguishable from trackball click events if the logic is the same

@procount
Copy link
Author

procount commented Dec 3, 2019

An interrupt just "pokes" the driver to say "go and look to see if there is anything you need to do".
In the touchscreen, you get an interrupt to say something has happened. The driver will then read the chip to see WHAT has happened, which could be nothing.
If several drivers share the same IRQ, then they are "poked" in turn. It's up to them what they then do.

@procount
Copy link
Author

procount commented Dec 4, 2019

@mikekscholz Looking further at the Hyperpixel touchscreen interrupt code, this is NOT written to be shared, so unfortunately I don't think you could get your trackball connected to it.

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

No branches or pull requests

3 participants