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

too low touch event polling rate with official Raspberry Pi 7inch screen #3227

Closed
ardera opened this issue Sep 12, 2019 · 15 comments
Closed

Comments

@ardera
Copy link

ardera commented Sep 12, 2019

If you open /dev/input/event0 directly, repeatedly read from it, and measure the interval between individual reads, you'll find that this interval is around 40ms, so 25 touch events per second / 25Hz.

However, the specs of the FT5406 say it can do up to 100Hz (in practice probably around 60Hz), and the source code of the official raspberry pi touchscreen driver says it polls the touchscreen with an interval of about 17ms, or 60Hz.

This doesn't seem to be the case. 60Hz and 25Hz touchscreen report rate is a huge difference for responsive touch applications. If you drag some object in a touch application, but your finger position only updates 25 times per second, then that object only redraws at 25fps too. The whole application will feel laggy.

To reproduce
Run this:

#include <linux/input.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char** argv) {
    int fd;
    struct input_event touch_event[8];
    struct timespec last_poll, this_poll;

    fd = open("/dev/input/event0", O_RDONLY);
    while (1) {
        ssize_t ok = read(fd, &touch_event, sizeof(touch_event));

        clock_gettime(CLOCK_MONOTONIC, &this_poll);
        printf(
            "Polling Frequency: %02.2fHz\n",
            1.0 / ((this_poll.tv_sec - last_poll.tv_sec) + (this_poll.tv_nsec - last_poll.tv_nsec) / 1000000000.0)
        );

        last_poll = this_poll;
    }
}

Expected behaviour
Expected is a 60Hz polling rate, as specified in the driver and in the FT5406 specs.

Actual behaviour
In reality the polling rate is 25Hz.

System

System Information
------------------

Raspberry Pi 3 Model A Plus Rev 1.0
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"

Raspberry Pi reference 2019-06-20
Generated using pi-gen, https://github.com/RPi-Distro/pi-gen, 150e25c4f8123a4c9c63e8dca1b4737fa6c1135c, stage5

Linux hpi 4.19.50-v7+ #896 SMP Thu Jun 20 16:11:44 BST 2019 armv7l GNU/Linux
Hardware        : BCM2835
Revision        : 9020e0
Serial          : 00000000e9058473
Throttled flag  : throttled=0x0
Camera          : supported=0 detected=0

Videocore information
---------------------

Jun 20 2019 16:13:08
Copyright (c) 2012 Broadcom
version a59fb7a74180be0111dbc5c18a37ec6df86f14a3 (clean) (release) (start_cd)

alloc failures:     0
compactions:        0
legacy block fails: 0 

When the FT5406 is in Monitor mode, it polls at 25Hz. However, if it then detects an input, it immediately switches to Active mode for a configurable time and polls at 60Hz. Maybe the time in active mode is somehow set too low, so that it in practice never really gets out of Monitor mode?

@JamesH65
Copy link
Contributor

JamesH65 commented Sep 16, 2019

Taken a quick look at the firmware side drivers, and that polls at 60Hz. So the delay is probably elsewhere.

edit: Linux side driver is the same - 60Hz polling.

@JamesH65
Copy link
Contributor

The monitor mode comment above may well be correct. The driver itself does nothing to switch in and out of any modes - just polls the chip at 60Hz.

@ardera
Copy link
Author

ardera commented Sep 16, 2019

Yep, but that change from Monitor to Active should be automatically. I think it's unlikely the mode switch doesn't happen, the driver shouldn't need to interfere with that at all. It's possible that somehow some settings of the FT5426 are changed by the firmware driver that are badly chosen.

But even then, it really bugs me that the interval is exactly 40ms. If the FT5426 and firmware/linux were running at different polling rates, you'd expect anything but an exact 40ms interval in userspace, wouldn't you? It should be more like sometimes 17, sometimes 34, 51, 68, etc.

EDIT: Just looked at the linux driver again, it doesn't check if the touch buffer contents changed at all.
So, even if the touch buffer it gets from the firmware driver is only updated at 25Hz (which it isn't), it should still report to userspace at 60Hz, shouldn't it? (Just that some of these userspace touch updates are actually bogus updates because the underlying touch buffer didn't change)

@JamesH65
Copy link
Contributor

Looking at the firmware side, and the datasheet, I suspect it is going in to active mode, but then dropping straight back to monitor mode. I'll do some tests to see if setting the timeout a little larger makes a difference.

@JamesH65
Copy link
Contributor

Quick question - running your test above, I get no events from the touchscreen at all. Moving the mouse gives me 62Hz update, but not events from the TS at all. Anything specific I need to set up?

@JamesH65
Copy link
Contributor

Ah, using /dev/input/mouse1 is what I need. Showing 25Hz using the default settings.

@ardera
Copy link
Author

ardera commented Sep 17, 2019

I just built a python GPIO I2C sniffer and looked at the traffic on i2c-0.

The VideoCore polls the FT5426 at 60Hz, but also, the FT5426 correctly replies with up-to-date touch data (nearly) every time. I measured across 10 seconds, and the average time between polls with up-to-date touch data was about 19ms. Not 17ms, but also far away from 40ms.

If you want to test it yourself, the repo is located here. It seems like you need to physically connect the touchscreen's i2c pins to the Pi for it to work. Sniffing pins 0&1 (where i2c-0 should be located) doesn't work for me, somehow.

What do you think? I personally am more and more convinced it's actually a linux driver bug. The VC <-> FT5426 comm. is working as it should (if my i2c sniffer is to be trusted), and that exact 40ms interval in userspace really shouldn't be there.

@6by9
Copy link
Contributor

6by9 commented Sep 17, 2019

BSC0 (the I2C controller behind /dev/i2c-0) can be pinmuxed to GPIOs 0&1, 28&29, or 44&45, but only one set at a time.
0&1 are presented on the 40 pin GPIO header.
It varies between Pi variants as to whether the camera and display are on 28&29 (0, 0W, A+, B+, 2) or 44&45 (Pi3 and 4).

The firmware has a thread for polling the touchscreen. It sleeps 17ms, and then reads the data into a buffer shared with the Linux kernel.
The Linux kernel driver rpi_ft5406 then polls that shared buffer every 17ms to create the input events - https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/input/touchscreen/rpi-ft5406.c#L73

@JamesH65
Copy link
Contributor

I just built a python GPIO I2C sniffer and looked at the traffic on i2c-0.

The VideoCore polls the FT5426 at 60Hz, but also, the FT5426 correctly replies with up-to-date touch data (nearly) every time. I measured across 10 seconds, and the average time between polls with up-to-date touch data was about 19ms. Not 17ms, but also far away from 40ms.

If you want to test it yourself, the repo is located here. It seems like you need to physically connect the touchscreen's i2c pins to the Pi for it to work. Sniffing pins 0&1 (where i2c-0 should be located) doesn't work for me, somehow.

What do you think? I personally am more and more convinced it's actually a linux driver bug. The VC <-> FT5426 comm. is working as it should (if my i2c sniffer is to be trusted), and that exact 40ms interval in userspace really shouldn't be there.

Useful information, I was unsure how to check if the controller was actually returning data at 60Hz. In your sniffing, did the data change at 60Hz, or 25Hz? I have tried setting the appropriate registers in the controller to set/change the monitor/active timings and see no difference in the overall poll rate in userspace, which make me wonder if the linux multitouch/input system has some setting I need to change to set the correct report rate.

@ardera
Copy link
Author

ardera commented Sep 17, 2019

In your sniffing, did the data change at 60Hz, or 25Hz?

That's what I meant, the data changed at 60Hz. There were some few occasions where the data didn't change between polls, but they are well within the margin of error.

EDIT: I'm currently looking at other multitouch drivers trying to find a difference, but so far I've found nothing.

BSC0 (the I2C controller behind /dev/i2c-0) can be pinmuxed to GPIOs 0&1, 28&29, or 44&45, but only one set at a time.
0&1 are presented on the 40 pin GPIO header.
It varies between Pi variants as to whether the camera and display are on 28&29 (0, 0W, A+, B+, 2) or 44&45 (Pi3 and 4).

Ah okay; the pinmux explains it all. Should've sniffed on 44&45 then.

@JamesH65
Copy link
Contributor

JamesH65 commented Sep 17, 2019

OK, so it appears the hardware is doing the right thing, firmware is doing the right thing, and the linux side of the driver is doing the right thing, but for the life of me I cannot find out if/where there are any rate control mechanisms in the linux input subsystem - there must be something dropping it back to 25Hz (and occasionally for one sample 12.5Hz). Will keep looking.

@JamesH65
Copy link
Contributor

JamesH65 commented Sep 17, 2019

Ah ha! Turns out the linux driver is NOT actually doing the right thing. The use of msleep_interruptible to do the millisecond timing is incorrect in this situation, where the delay is <20ms (see https://github.com/torvalds/linux/blob/a351e9b9fc24e982ec2f0e76379a49826036da12/Documentation/timers/timers-howto.txt). Replacing it with usleep_range and I get 60Hz refresh, which looks a LOT better. I'll do a PR.

@JamesH65
Copy link
Contributor

PR is here #3238

@ardera
Copy link
Author

ardera commented Sep 17, 2019

Nice!

popcornmix added a commit to raspberrypi/firmware that referenced this issue Sep 17, 2019
kernel: Fix poll rate on touchscreen
See: raspberrypi/linux#3227

firmware: Round up HDMI0 minimum core clock

firmware: board_info: Support bcm2710- and bcm2837- Pi 2 DTBs
See: raspberrypi/linux#3234

firmware: power: bcm2711: Rescale the GPIO pad power

firmware: brfs: Add GENET driver for 2711
firmware: bootloader_state: Add network state and bootmode configuration
firmware: bootloader_state: Fix mask for EEPROM header magic
popcornmix added a commit to Hexxeh/rpi-firmware that referenced this issue Sep 17, 2019
kernel: Fix poll rate on touchscreen
See: raspberrypi/linux#3227

firmware: Round up HDMI0 minimum core clock

firmware: board_info: Support bcm2710- and bcm2837- Pi 2 DTBs
See: raspberrypi/linux#3234

firmware: power: bcm2711: Rescale the GPIO pad power

firmware: brfs: Add GENET driver for 2711
firmware: bootloader_state: Add network state and bootmode configuration
firmware: bootloader_state: Fix mask for EEPROM header magic
@JamesH65
Copy link
Contributor

A useful tool for testing events was found here https://github.com/ian-kelling/evhz

pelwell pushed a commit that referenced this issue Sep 19, 2019
Was running at 25Hz, rather than he expected 60. Only been doing it
for the last 5 years....

Replace msleep_interruptible with usleep_range as the msleep call
is not accurate for times < 20ms.

Fixes: #3227

Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
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