The software side of this project is a hack on a hack right now.
On the very bottom we have gpiots kernel module to timestamp interrupts from GPIO.
One layer above there is a C program that I wrote that does the timing calculation and output x/y/button status to the standard output.
One layer above there is a Python (Pygame) program that I wrote that takes this information from stdin and actually does something: a test/demo to show where it thinks lightpen is pointing at.
That wasn't enough so I wrote another Python program that does the calibration and then passes the x/y/button states back into Linux kernel through uinput interface.
So we've come a full circle - some information is decoded from gpio and timing inside the kernel, then goes through two userland processes just to be passed back into the kernel uinput subsystem to be made available for any software.
I'm so proud of myself and modern ducktape software engineering.
The clean solution will be of course to fork gpiots module, do the calculations there and pass events without leaving kernel space. This new module needs an interface where calibration info would be provided from a user program.
I have included everything done so far into "lp-20200702.tar.gz" archive that you can find in the "Files" section.
The way it's supposed to work is
- go to gpiots/ folder and build the module, as root run the insmod.sh script to copy the module into proper space and load it into kernel with GPIO 17 and 23 options
- do "make" to compile lp-gpiots.c program
- pip install uinput library for Python
Once you have it, in a shell pipe lp-gpiots output into lp-demo.py to see a simple demo on the framebuffer:
./lp-gpiots | python3 -u lp-demo.py
Or you can pass the events to uinput:
./lp-gpiots | python3 -u lp-uinput.py
These can be viewed using evtest program:
My calibration is way off, but this setup already allows to play NES lightgun games, like Duck Hunt.