Timing is everything

A project log for Light pen support for RetroPie

Can a Raspberry Pi with CRT display support 8-bit era light pen?

maciej-witkowiakMaciej Witkowiak 06/07/2020 at 17:050 Comments

The operation of the light pen depends on accurate time measurements. On a C64/128 this is realized in the hardware - the VIC chip latches X/Y position when light sensor is triggered.

The plan

I didn't have high hopes for Raspberry Pi running Linux to be able to measure time with required accuracy. This is the timing diagram for PAL:

The refresh rate is 50Hz, so we have 1/50s=20ms for every frame. Every line takes 64 microseconds. I would be very happy with being able to detect at least 4 regions on the line, not even aiming for pixel-level resolution.

This means that I need to be able to accurately measure time since a fixed time 0 (e.g. middle of the screen, when I release the button after calibration) with known time per frame. I need better than 64us resolution to determine lines and 16us resolution to determine 4 regions in every line.

It's not possible to do from userspace. Fortunately I found a very neat project on GitHub where someone else had the same need.


This is a kernel module that creates /dev/gpiotsXX devices and provides timestamps for interrupts coming from selected GPIO pins.

Initially I tested it on another Raspberry Pi which is connected to a GPS receiver with PPS line. The numbers from gpio_test.c were promising:

428 966 912
429 966 914
430 966 912
431 966 911

 The PPS signal arrives every second, so the difference between every number should be exactly 1000000. It's not exactly that, but it's close. After running for a long time I determined that the resolution was about 3us, so I should be able to detect not four fields per line but up to 16.

Dreams shattered

Unfortunately it doesn't work like that on a real RPi connected to a real CRT. There is a lot going on and I'm still not sure if I didn't overlook anything obvious.

Well it kind of works. After connecting light pen and trying it out I was able to:

...and that's about it. I tried to count a fixed amount of time since time_0 for every frame and use the difference between the elapsed time and the time when light sensor interrupt arrived to calculate what should be the offset.

I got no consistency at all, the numbers are all over the place, it was not possible to determine even the Y position to any accuracy. I was expecting to have drift or low accuracy, but not something that seems to be random.

You can find the source code for my play/test program attached. 

This somewhat contradicts the GPS PPS test, and I'm not really sure why.