Close

Native VSYNC event

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 04/11/2021 at 21:260 Comments

Apparently there is a way to tie a function to hardware VSYNC event. I found it in a closed issue for Raspberry Pi userland: https://github.com/raspberrypi/userland/issues/218

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>

#include "bcm_host.h"

static DISPMANX_DISPLAY_HANDLE_T   display;
unsigned long lasttime = 0;

void vsync(DISPMANX_UPDATE_HANDLE_T u, void* arg) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    unsigned long microseconds = (tv.tv_sec*1000000)+tv.tv_usec;
    printf("%lu\tsync %lu\n", microseconds,microseconds-lasttime);
    lasttime = microseconds;
}

int main(void)
{
    bcm_host_init();
    display = vc_dispmanx_display_open( 0 );

    vc_dispmanx_vsync_callback(display, vsync, NULL);
    sleep(1);
    vc_dispmanx_vsync_callback(display, NULL, NULL); // disable callback

    vc_dispmanx_display_close( display );
    return 0;
} 

To compile it you need to add paths to /opt/vc and link with libbcm_host.so, like

gcc test.c -o test -I/opt/vc/include -L/opt/vc/lib -lbcm_host

I have copied this code into my repository https://github.com/ytmytm/rpi-lightpen/blob/master/vsync-rpi.c

That issue is closed and this snippet works for me. The output is about 20000us but not stable at all.

There is a lot of jitter because the time is saved only in the userspace, not as quickly as possible in kernel. Even if I try to tie my routine somewhere in the kernel, I don't know how much time is needed to service these events. This is some kind of message queue between CPU and GPU. Unfortunately it's not as simple as a direct IRQ.

So it's a good way to wait until VSYNC but it's not precise enough for lightpen needs.

Discussions