Index: [thread] [date] [subject] [author]
  From: Thomas Tanner <tanner@gmx.de>
  To  : GGI mailing list <ggi-develop@eskimo.com>
  Date: Fri, 07 Aug 1998 19:44:28 +0000

ANNOUNCE: vertical retrace sync via RT-Linux

HI

 I've written a simple RT-Linux module that does
 vertical retrace synchronisation on VGA compatible cards.
 A RT-Linux task is called on every vertical retrace and will call a
 function of the KGI-driver, which itself may, for example, set the palette 
 and switch the displayed frame.
 You can download the module and the instructions how to use it from
 my home page: http://home.pages.de/~tanner/ggi.html#vsync
 Special thanks go to Bernhard Kuhn who wrote the initial code and helped me a lot.

 RT-Linux is a pico-OS that runs Linux as its idle task and 
 allows special tasks to run in realtime (even under heavy load).
 The good thing about RT-Linux is that you do not notice any difference
 to a normal Linux system unless you start a RT-Linux task.
 That's the reason why RT-Linux will get into Linux 2.3 and 
 will be enabled by default in Linux 2.4
 
 Attached is the source of the module.

 RT-Linux: http://www.rtlinux.org

-- 
Thomas Tanner -----------------------------
email: tanner@gmx.de tanner@ggi-project.org
web:   http://home.pages.de/~tanner
GGI:   http://www.ggi-project.org
/* 
 *  Vertical retrace synchronisation with RT-Linux (VGA)
 *
 *  Copyright (C) 1998 by Thomas Tanner <tanner@ggi-project.org>
 *  Copyright (C) 1998 by Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <asm/io.h>

#include <rtl_sched.h>
#include <rtl_fifo.h>

/* VGA vrt bit */
#define VRT_BIT() (inb(0x3DA) & 8)

/* ticks per µs */
#define TICKS(us) (RT_TICKS_PER_SEC * us) / 1000000L

void print_time(int fifo, RTIME time)
{
        char *hex="0123456789ABCDEF\n";
        int i;

#ifdef BIG_ENDIAN
        for(i = 0; i < sizeof(RTIME); i++) {
#else
        for(i = sizeof(RTIME)-1; i >= 0; i--) {
#endif
                rtf_put(fifo, &hex[(char) (time >> (i * 4)) & 0xF], 1);
        }
        rtf_put(fifo, &hex[16], 1);
}

RTIME period;

void vrt_handler(void)
{
        /* write to first FIFO */
/*        rtf_put(1, ".\n", 2);*/
        print_time(1, period);
}

/* the realtime task */
RT_TASK vsync_task;

void periodic_vsync_task(int t)
{
        RTIME time, last;
	
        /* vsync calibration */
        period = 0;
        do {
		last = period;
                /* wait for low->high transition and then get the time */
                while(VRT_BIT());
                while(!VRT_BIT());
                time = rt_get_time();
                /* wait for high->low transition and then get the time */
                while(VRT_BIT());
                while(!VRT_BIT());
                period = rt_get_time();
                /* calculate difference */
                period -= time;
        } while (abs(period - last) > 2);
	
        /* wait for high->low to start the periodic task */
        while(VRT_BIT());
        /* start */
        for(;;) {
                /* wait for low->high (max. 20µs) */
                while(!VRT_BIT());
                /* ok. prepare for next time */
	        /* substract 20µs to be able to wait for the vrt */
                rt_task_make_periodic(&vsync_task, 
			rt_get_time(), period - TICKS(20));
                /* call the vrt handler */
                vrt_handler();
                /* wait for next vrt */
                rt_task_wait();
        }
}


void init_vsync_handler(void)
{
        /* create output FIFO */
        rtf_create(1, 4096);
        /* create realtime task for vertical retrace synchronisation */
        rt_task_init(&vsync_task, periodic_vsync_task, 0, 2048, 1);
        /* now start the task */
        rt_task_make_periodic(&vsync_task, rt_get_time(), TICKS(1000000));
}

void cleanup_vsync_handler(void)
{
        /* delete the realtime task */
        rt_task_delete(&vsync_task);
        /* destroy the output FIFO */
        rtf_destroy(1);
}

int init_module(void)
{
        init_vsync_handler();
        return 0;
}

void cleanup_module(void)
{
        cleanup_vsync_handler();
}



Index: [thread] [date] [subject] [author]