From keith.haynes@earthlink.net  Fri Jun 18 10:05:52 2004
Return-Path: <keith.haynes@earthlink.net>
X-Original-To: baker@cs.fsu.edu
Delivered-To: baker@cs.fsu.edu
Received: from cs.fsu.edu (envoy.cs.fsu.edu [128.186.120.106])
	by mail.cs.fsu.edu (Postfix) with ESMTP id 4F0D4F29B1
	for <baker@cs.fsu.edu>; Fri, 18 Jun 2004 10:05:52 -0400 (EDT)
Received: from falcon.mail.pas.earthlink.net ([207.217.120.74]) by cs.fsu.edu with Microsoft SMTPSVC(6.0.3790.0);
	 Fri, 18 Jun 2004 10:05:51 -0400
Received: from thecount.psp.pas.earthlink.net ([207.217.78.22])
	by falcon.mail.pas.earthlink.net with esmtp (Exim 3.33 #1)
	id 1BbK06-0001Q8-00
	for baker@cs.fsu.edu; Fri, 18 Jun 2004 07:05:50 -0700
Message-ID: <687476.1087567550914.JavaMail.root@thecount.psp.pas.earthlink.net>
Date: Fri, 18 Jun 2004 10:05:50 -0400 (GMT-04:00)
From: Keith Haynes <keith.haynes@earthlink.net>
Reply-To: Keith Haynes <keith.haynes@earthlink.net>
To: baker@cs.fsu.edu
Subject: HRT Video Driver 1
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary=---------------------------16533773738594844211914544919
X-Mailer: Earthlink Zoo Mail 1.0
X-OriginalArrivalTime: 18 Jun 2004 14:05:51.0743 (UTC) FILETIME=[5D2728F0:01C4553D]
X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on mail.cs.fsu.edu
X-Spam-Level: 
X-Spam-Status: No, hits=-4.9 required=5.0 tests=BAYES_00,L_TO_ME 
	autolearn=ham version=2.63
Status: RO
Content-Length: 28371
Lines: 1072

-----------------------------16533773738594844211914544919
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Professor, here are the files for my project
-----------------------------16533773738594844211914544919
Content-Disposition: attachment; filename="hrt.c"
Content-Type: application/octet-stream; name=hrt.c
Content-Transfer-Encoding: 7bit

#include <linux/module.h>
#include <linux/pci.h>
//#include <linux/init.h>
#include <linux/videodev.h>
//#include <linux/list.h>
#include <linux/delay.h>
#include <linux/mm.h>
//#include <asm/msr.h>
#include "i2c.h"
#include "hrt.h"
#include "sysdep.h"


int icounter = 0;
long start_time = 0;
long total_time;

/* Major number for hrtmem device */
static unsigned int hrt_major = 0;



/**
 * struct hrt - the main device struct. This represents the card.
 */
struct hrt {
        unsigned long physaddr; /* Physical address */
        unsigned long virtaddr; /* Virtual address (was ioremapped) */
        struct pci_dev *pcidev; /* PCI device */
        struct semaphore sem; /* Protective mutex */
        unsigned int field_bit; /* Which field (even or odd) is capturing */
        unsigned int streaming; /* streaming mode */
                                                                                                                             
        //Haynes Fields
        int irq;
        int mem_set;
        int addr_size;
        int type_pci;
        int irq_status;  // -1 not verified, 0 disabled, 1 enabled
        int live_status;
        int type_color;
        int hrt_device_id;
        int rows; //max rows
        int cols; //max cols
        // defines window size for transfers
        int wrs;
        int wre;
        int wcs;
        int wce;
        unsigned char buf[2][HRT_WIDTH * HRT_HEIGHT];
	int db_status;
        int read_buffer;
        int last_frame;
        long buf_count[2];
        struct semaphore sem_buf[2]; /* Protective mutex */
	int capture_mode;
};
                                                                                                                             



#define HRT_MAX_DEVS 3

static struct hrt hrtdevs[HRT_MAX_DEVS];
static int hrtdevs_installed;
void grabber_tasklet0 (unsigned long);
void grabber_tasklet1 (unsigned long);
void grabber_tasklet2 (unsigned long);
DECLARE_TASKLET (fg_tasklet0, grabber_tasklet0,0);
DECLARE_TASKLET (fg_tasklet1, grabber_tasklet1,0);
DECLARE_TASKLET (fg_tasklet2, grabber_tasklet2,0);


long capture_frame(struct hrt *hd)
{
	unsigned int i;
	int a = hd->wrs, b = hd->wre, c = hd->wcs, d = hd->wce;
	unsigned long  ll = d - c + 1; // line length
	unsigned long yaddr = hd->virtaddr + HRT_Y_LOW_REG;
	unsigned char *fp = (unsigned char *) hd->virtaddr + c; //frame pointer
	long size;
	unsigned char *bp = NULL; //buffer pointer
	int wb = (hd->read_buffer + hd->db_status) % 2;
	writeb(0x99, hd->virtaddr + 0x2000);
	wmb();
	unsigned long delay = jiffies + 2;
	while (delay <= jiffies) 
	{}
	bp = (unsigned char *) &hd->buf[wb]; //buffer pointer
	writeb(0, yaddr + 1);
	for (i=a;i<=b;i++)
	{
		if (i>255) writeb(1,yaddr + 1);
		writeb(i, yaddr);
		wmb();
		memcpy(bp,fp,ll);
		bp = bp + ll;
	}
	size = ll * (b - a + 1);

	hd->buf_count[wb] = size;
	writeb(0x91, hd->virtaddr + 0x2000);
	wmb();
	hd->read_buffer = (hd->read_buffer + hd->db_status) % 2;
	return size;
}

long capture_frame_fast(struct hrt *hd)
{
	hd->db_status = 0;
	int fd = readb(hd->virtaddr + 0x2000) & 1;
	rmb();
	while (fd == hd->last_frame)
	{
		fd = readb(hd->virtaddr + 0x2000) & 1;
		rmb();
	}
	hd->last_frame = (hd->last_frame + 1) % 2;

	unsigned int i;
	int a = hd->wrs, b = hd->wre, c = hd->wcs, d = hd->wce;
	unsigned long  ll = d - c + 1; // line length
	unsigned long yaddr = hd->virtaddr + HRT_Y_LOW_REG;
	unsigned char *fp = (unsigned char *) hd->virtaddr + c; //frame pointer
	long size;
	unsigned char *bp = NULL; //buffer pointer
	int spacer;
	int high_set = 0;
	int wb = (hd->read_buffer + hd->db_status) % 2;
	if (fd == (a % 2))
	{ 
		a++;
		spacer = 1;
	}
	else spacer = 0;

	if (fd == (b % 2)) b--;

	bp = (unsigned char *) &hd->buf[wb]; //buffer pointer
	bp = bp + (spacer * ll);
	size = ll * (b - a + 1);
	writeb(0, yaddr + 1);
	for (i=a;i<=b;i += 2)
	{
		if (i>255 && !high_set)
		{
			writeb(1,yaddr + 1);
			wmb();
			high_set = 1;
		}
		writeb(i, yaddr);
		wmb();
		memcpy(bp,fp,ll);
		bp = bp + ll * 2;
	}
	hd->buf_count[wb] = size;
	hd->read_buffer = (hd->read_buffer + hd->db_status) % 2;
	return size;
}

long capture_frame_turbo(struct hrt *hd)
{
	hd->db_status = 0;
	int fd = readb(hd->virtaddr + 0x2000) & 1;
	rmb();
	while (fd == hd->last_frame)
	{
		fd = readb(hd->virtaddr + 0x2000) & 1;
		rmb();
	}
	hd->last_frame = (hd->last_frame + 1) % 2;

	unsigned int i;
	int a = hd->wrs, b = hd->wre, c = hd->wcs, d = hd->wce;
	unsigned long  ll = d - c + 1; // line length
	unsigned long yaddr = hd->virtaddr + HRT_Y_LOW_REG;
	unsigned char *fp = (unsigned char *) hd->virtaddr + c; //frame pointer
	long size = 0;
	unsigned char *bp = NULL; //buffer pointer
	int spacer;
	int high_set = 0;
	int wb = (hd->read_buffer + hd->db_status) % 2;
	if (fd == (a % 2))
	{ 
		a++;
		spacer = 1;
	}
	else spacer = 0;

	if (fd == (b % 2)) b--;

	bp = (unsigned char *) &hd->buf[wb]; //buffer pointer
	bp = bp + (spacer * ll);
	writeb(0, yaddr + 1);
	for (i=a;i<=b;i += 2)
	{
		if (i>255 && !high_set)
		{
			writeb(1,yaddr + 1);
			wmb();
			high_set = 1;
		}
		writeb(i, yaddr);
		wmb();
		memcpy(bp,fp,ll);
		bp = bp + ll;
		size += ll;
	}
	hd->buf_count[wb] = size;
	hd->read_buffer = (hd->read_buffer + hd->db_status) % 2;
	return size;
}




void do_grabber(int x)
{
	icounter++;
	capture_frame(&hrtdevs[x]);
	if (hrtdevs[x].streaming)
	{
		writeb(1,hrtdevs[x].virtaddr + HRT_INTERRUPT_ENABLE);
		wmb();
	}
}


void grabber_tasklet0 (unsigned long hd)
{
	do_grabber(0);
}

void grabber_tasklet1 (unsigned long hd)
{
	do_grabber(1);
}

void grabber_tasklet2 (unsigned long hd)
{
	do_grabber(2);
}

int hrt_open(struct inode *inode, struct file *filp)
{
	int minor;
	minor = MINOR(inode->i_rdev);
	filp->private_data = &hrtdevs[minor];
	MOD_INC_USE_COUNT;
	return 0;
}

static int hrt_direct_mmap(struct file *filp,
                           struct vm_area_struct *vma)
{
        struct hrt *hrtdev = filp->private_data;
                                                                                                                             
        printk("<1>hrt_direct_mmap\n");
                                                                                                                             
        vma->vm_flags |= (VM_IO | VM_RESERVED);
                                                                                                                             
                                                                                                                             
        if (remap_page_range(vma->vm_start, __pa(&hrtdev->buf[0]), 
		512 * 480, vma->vm_page_prot))
                return -EAGAIN;
                                                                                                                             
        return 0;
}




int hrt_mmap(struct file *filp, struct vm_area_struct *vma)
{
	printk("<1>mmap called offset\n");

        if (vma->vm_pgoff == (HRT_MAGIC_MMAP_OFFSET / PAGE_SIZE))
	{
                int ret;
		struct hrt *hd = filp->private_data;
		if (down_interruptible(&hd->sem)) return -ERESTARTSYS;
                ret = hrt_direct_mmap(filp, vma);
                up(&hd->sem);
                return ret;
        }
	return 0;
}

static int hrt_release(struct inode *inode, struct file *file)
{
	MOD_DEC_USE_COUNT;
	return 0;
}

static int hrt_ioctl(struct inode *inode, struct file *filp,
		     unsigned int cmd, unsigned long arg)
{
	struct hrt *hd = filp->private_data;
	hrt_wnd *hwp = (hrt_wnd *) arg;
	int val = arg;
	switch (cmd)
	{
		case HRT_START_STREAM:
		if (down_interruptible(&hd->sem)) return -ERESTARTSYS;
		hd->streaming = 1;
		writeb(1,hd->virtaddr + HRT_INTERRUPT_ENABLE);
		up(&hd->sem);
		break;

		case HRT_STOP_STREAM:
		if (down_interruptible(&hd->sem)) return -ERESTARTSYS;
		hd->streaming = 0;
		writeb(0,hd->virtaddr + HRT_INTERRUPT_ENABLE);
		up(&hd->sem);
		break;

		case HRT_SET_WND:
		if (down_interruptible(&hd->sem)) return -ERESTARTSYS;
		if (hwp->rs < 0) hwp->rs = 0;
		if (hwp->cs < 0) hwp->cs = 0;
		if (hwp->rs > hd->rows - 5) hwp->rs = hd->rows - 5;
		if (hwp->cs > hd->cols - 5) hwp->cs = hd->cols - 5;
		if (hwp->re > hd->rows) hwp->re = hd->rows - 1;
		if (hwp->ce > hd->cols) hwp->ce = hd->cols - 1;
		if (hwp->re <= hwp->rs) hwp->re = hwp->rs + 4;
		if (hwp->ce <= hwp->cs) hwp->ce = hwp->cs + 4;
		hd->wrs = hwp->rs;
		hd->wre = hwp->re;
		hd->wcs = hwp->cs;
		hd->wce = hwp->ce;
		up(&hd->sem);
		break;

		case HRT_GET_WND:
		if (down_interruptible(&hd->sem)) return -ERESTARTSYS;
		hwp->rs = hd->wrs;
		hwp->re = hd->wre;
		hwp->cs = hd->wcs;
		hwp->ce = hd->wce;
		up(&hd->sem);
		copy_to_user((void *) arg, hwp, sizeof(struct hrt_wnd));
		break;

		case HRT_DOWN_USER_COUNT:
		MOD_DEC_USE_COUNT;
		MOD_DEC_USE_COUNT;
		break;

		case HRT_SET_CAPTURE_MODE:
		if (val >= 0 && val <= 1) hd->capture_mode = val;
		break;

		case HRT_DB_ON:
		hd->db_status = 1;
		break;

		case HRT_DB_OFF:
		hd->db_status = 0;
		break;

	}
	return 0;
}

static int hrt_read(struct file *filp, char *buf, size_t count,
		    loff_t * ppos)
{
	struct hrt *hd = filp->private_data;
	int rb = hd->read_buffer;

	if (down_interruptible(&hd->sem_buf[rb])) return -ERESTARTSYS;
	if (hd->streaming)
	{
		count = hd->buf_count[rb];
		copy_to_user(buf, &hd->buf[rb], count);
	}
	else
	{
		count = capture_frame_fast(hd);
		copy_to_user(buf, &hd->buf[rb], count);
	}
	up(&hd->sem_buf[rb]);
	return count;
}


/**
 * hrt_fops - fops for /dev/video<n>
 */
static struct file_operations hrt_fops = {
	.owner = THIS_MODULE,
	.open = hrt_open,
	.mmap = hrt_mmap,
	.release = hrt_release,
	.ioctl = hrt_ioctl,
	.read = hrt_read,
};

/**
 * hrt_probe - check that we have a device as the specified address.
 *  Assume the memory region is already mapped.
 *  The address has to be a virtual address mapped to the device I/O space.
 */
int hrt_probe(unsigned long addr)
{
	unsigned char oldval1, oldval2, oldval3, newval2;
	unsigned int oldaddr;

	/* save the old values at the address */
	oldval1 = readb(HRT_CONTROL_REG + addr);
	rmb();
	oldaddr = readw(HRT_Y_LOW_REG + addr);
	rmb();
	
	/* freeze the frame grabbing, immediately */
	writeb(0x5B, HRT_CONTROL_REG + addr);
	wmb();
      
	/* write a new value to the first byte in the first raster/row */
	writew(0, HRT_Y_LOW_REG + addr);
	wmb();
	oldval2 = readb(addr);
	rmb();
	writeb(~oldval2, addr);
	wmb();
	
	/* write oldval2 to the first byte of the next raster/row */
	writew(1, HRT_Y_LOW_REG + addr);
	wmb();
	oldval3 = readb(addr);
	rmb();
	writeb(oldval2, addr);
	wmb();
	
	/* read the value at the previous raster/row */
	writew(0, HRT_Y_LOW_REG + addr);
	wmb();
	newval2 = readb(addr);
	rmb();
	
	/* restore the old values */
	writeb(oldval2, addr);
	wmb();
	writew(1, HRT_Y_LOW_REG + addr);
	wmb();
	writeb(oldval3, addr);
	wmb();
	writeb(oldaddr, HRT_Y_LOW_REG + addr);
	wmb();
	writeb(oldval1, HRT_CONTROL_REG + addr);
	wmb();
	
	return (newval2 == (unsigned char)~oldval2);
}



int detect_devices(void)
{
	int pp, result, found, devices, holder = 0;
	pp = pci_present();
	struct pci_dev *dev = NULL;
	hrtdevs_installed = 0;
	
	if (pp == 0) 
	{
		printk("<1>PCI is not present.\n");
		//perform ISA detection
	}
	else
	{
	for (devices=0; devices<HRT_DEVICES;devices++)
	{
		dev = NULL;
		//find Grayscale Devices
		for (found = 0; found < HRT_MAX_DEVS;found++)
		{
			hrtdevs[found].irq = 0;
			dev = pci_find_device(HRT_VENDOR_ID,HRT_DEVICE_IDS[devices],dev);
			if (dev)
			{
				hrtdevs[found].pcidev = dev;
				result = pci_read_config_byte(hrtdevs[found].pcidev, 
					PCI_INTERRUPT_LINE,(u8 *) &hrtdevs[found].irq);
				hrtdevs_installed++;
				hrtdevs[found].type_pci = 1;
				hrtdevs[found].type_color = 0;
				hrtdevs[found].irq_status = -1;
				hrtdevs[found].hrt_device_id = HRT_DEVICE_IDS[devices];
				printk("<1>Found Device - %d\n", hrtdevs[found].hrt_device_id);
				printk("<1>IRQ found at %d\n", hrtdevs[found].irq);
			}
			else
			{
				holder = found;
				break;
			}
		}
	}
	}
	return hrtdevs_installed;
}


int hrt_try_addresses(int i)
{
	int OK = 0, try, mem_ok, virt_ok;
	if(hrtdevs[i].type_pci) pci_enable_device(hrtdevs[i].pcidev);
	OK = 0;
	try = 0;
	while (!OK && try < HRT_NUM_OF_ADDRESSES)
	{
		if (try == 0) //PnP enabled Jumper A On 
			hrtdevs[i].physaddr = pci_resource_start(hrtdevs[i].pcidev,0);
		else 
			hrtdevs[i].physaddr = HRT_ADDRESSES[try];

		hrtdevs[i].addr_size = BYTES_NEEDED;
		if(!request_mem_region(hrtdevs[i].physaddr,hrtdevs[i].addr_size, "hrt"))
		{
			mem_ok = 0;
		}
		else mem_ok = 1;

		if (mem_ok)
		{
			hrtdevs[i].virtaddr = (unsigned long) 
				ioremap_nocache(hrtdevs[i].physaddr, hrtdevs[i].addr_size);
			virt_ok = hrt_probe(hrtdevs[i].virtaddr);
		}
		else
		{
			virt_ok = 0;
		}
			

		if(!virt_ok && mem_ok)
		{
			release_mem_region(hrtdevs[i].physaddr,hrtdevs[i].addr_size);
			iounmap((unsigned char *) hrtdevs[i].virtaddr);
			hrtdevs[i].mem_set = 0;
		}
		else if (virt_ok && mem_ok)
		{
			hrtdevs[i].mem_set = 1;
			printk("<1>Memory Address found at %lX\n", hrtdevs[i].physaddr);
			OK = 1;
			
		}
		try++;
	}
	if (!OK)
	{
		printk("<1>Card %d failed to initialize\n",i);
		return OK;
	}
	return OK;
}

void hrt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	disable_irq(irq);
	int i, target = 0;
	for (i=0;i<hrtdevs_installed;i++)
		if (hrtdevs[i].irq == irq) target = i;
	writeb(0,hrtdevs[target].virtaddr + HRT_INTERRUPT_ENABLE);
	wmb();
	enable_irq(irq);
	if (target == 0) tasklet_schedule(&fg_tasklet0);
	else if (target == 1) tasklet_schedule(&fg_tasklet1);
	else tasklet_schedule(&fg_tasklet2);

}


/**
 * hrt_dev_init - initializes a device. Assumes hrtdev->virtaddr
 *  has been set to an ioremap'd address.
 */
int hrt_dev_init(struct hrt *hrtdev)
{
	/* We don't start in streaming mode */
	hrtdev->streaming = 0;
	
	hrtdev->last_frame = 0;
	hrtdev->db_status = 0; //double buffering off
	hrtdev->read_buffer = 0;
	hrtdev->buf_count[0] = 0;
	hrtdev->buf_count[1] = 0;


	/* Initialize semaphore */
	sema_init(&hrtdev->sem, 1);
	sema_init(&hrtdev->sem_buf[0], 1);
	sema_init(&hrtdev->sem_buf[1], 1);

	

	/* Read the field id bit (should be 0 since we're shouldn't be
	   in live mode yet) */
	hrtdev->field_bit = readb(hrtdev->virtaddr + HRT_CONTROL_REG) & 1;

	/* Put the card into Live mode */
	writeb(HRT_LIVE_CMD, hrtdev->virtaddr + HRT_CONTROL_REG);

	hrtdev->rows = HRT_HEIGHT;
	hrtdev->cols = HRT_WIDTH;
	hrtdev->wrs = 0;
	hrtdev->wcs = 0;
	hrtdev->wre = HRT_HEIGHT - 1;
	hrtdev->wce = HRT_WIDTH - 1;

	if (hrtdev->irq)
	{
		int ri;
		ri = request_irq(hrtdev->irq, hrt_interrupt, SA_INTERRUPT, "hrt", NULL);
		if (ri) printk("<1>IRQ request failed\n");
		else
		{
			printk("<1>IRQ request succeeded\n");
			if(hrtdev->streaming)
				writeb(0x01, hrtdev->virtaddr + HRT_INTERRUPT_ENABLE);
			wmb();
		}
	}

	return 0;
}


int init_module(void)      
{ 
	int i, result;
  	result = register_chrdev(hrt_major, "hrt", &hrt_fops);
  	if (result < 0) return result;
  	if (hrt_major == 0) hrt_major = result;
	detect_devices();
	for (i=0;i<hrtdevs_installed;i++)
	{
		if(hrt_try_addresses(i) > 0)
		{
			result = hrt_dev_init(&hrtdevs[i]);
			if (result < 0) return result;
			else
			{
				printk("<1>Device %d initialized\n",i);
				init_i2c(hrtdevs[i].virtaddr);

			}
		}
	}
	return 0; 
}

void cleanup_module(void)  
{ 
	int i;
	int fps;
	fps = (double) icounter / (double) ((double) total_time / (double) HZ);
	unregister_chrdev(hrt_major, "hrt");
	for (i=0;i<hrtdevs_installed;i++)
	{
		if (hrtdevs[i].irq_status>=0) printk("<1>Interrupt operation verified - %d\n", i); 
		free_irq(hrtdevs[i].irq, NULL);
		shutdown_i2c(hrtdevs[i].virtaddr);
		if (hrtdevs[i].mem_set)
		{
			release_mem_region(hrtdevs[i].physaddr,hrtdevs[i].addr_size);
			iounmap((unsigned char *) hrtdevs[i].virtaddr);
		}
	}
	printk("<1>Interrupt counter - %d\n", icounter); 
	printk("<1>Frame Rate - %d\n", fps); 
	printk("<1>HRT Driver Removed\n"); 
}



-----------------------------16533773738594844211914544919
Content-Disposition: attachment; filename="hrt.h"
Content-Type: application/octet-stream; name=hrt.h
Content-Transfer-Encoding: 7bit

/*
 * File Name : hrt.h
 * 
 * This is a device driver for the High Resolution Technologies
 * Pixelsmart 512-8 frame grabber.

 * This file contains structures, constants, and ioctl numbers in
 * the driver that a user program might wish to use.

 *         Copyright (C) 2003, Florida State University
 *
 * This is free software; you can redistribute it and/or modify it under 
 * terms of the GNU General Public License as published  by the Free Soft- 
 * ware Foundation, Version 2.  This software is distributed in the hope
 * that it will be useful, but WITH OUT ANY WARRANTY;  without even the
 * implied warranty of MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for  more details. You should have
 * received  a copy of the GNU General Public License distributed with this
 * software; see file COPYING.  If not, write to  the Free Software Foundation,
 * 59 Temple Place - Suite 330,  Boston, MA 02111-1307, USA.
 */
#include <linux/ioctl.h>


/**
 * Card specific constants
 */
#define HRT_VENDOR_ID         0x0004
#define HRT_DEVICE_ID_GRAY    0x0404
#define HRT_DEVICE_ID_COLOR   0x0408

#define HRT_DEVICES 2

const int HRT_DEVICE_IDS[] = {
	HRT_DEVICE_ID_COLOR,
	HRT_DEVICE_ID_GRAY
};

#define HRT_NUM_OF_ADDRESSES 9
#define HRT_MAX_BPP 2 //Max bits per pixel

const int HRT_ADDRESSES[] = {
	0, //filled in by PnP address
	0xC0000,
	0xC4000,
	0xC8000,
	0xCC000,
	0xD0000,
	0xD4000,
	0xD8000,
	0xDC000
};

#define HRT_CONTROL_REG       0x2000
#define HRT_Y_LOW_REG         0x2002
#define HRT_Y_HIGH_REG        0x2003
#define HRT_INTERRUPT_ENABLE  0x2005

/* The unique I2C bus address of the SAA7110 (A/D) device */
#define HRT_AD_DEVICE_ID (128+16+8+4)

/* NTSC 8-bit greyscale */
#define HRT_WIDTH             512
#define HRT_HEIGHT            480
#define HRT_BYTES_PER_PIXEL   1
#define HRT_BYTES_PER_LINE    (HRT_WIDTH * HRT_BYTES_PER_PIXEL)
#define HRT_FRAMESIZE         (HRT_WIDTH * HRT_HEIGHT * HRT_BYTES_PER_PIXEL)

/* Number of bytes of the device's memory that we ioremap() */
#define BYTES_NEEDED          0x4000

/*
 * The commands for freeze, live, etc.
 */
#define HRT_FIELD_MASK        0x01
#define HRT_LIVE_CMD          0x91
#define HRT_FREEZE_IMM_CMD    0x5B
#define HRT_FREEZE_NEXT_CMD   0x99

/* A/D registers */
#define HRT_BRIGHTNESS_REG    0x19
#define HRT_CONTRAST_REG      0x13

#define HRT_VID_TYPE         (VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME)

/* Maximum number of buffers for streaming */
#define MAX_CAPTURE_BUFFERS  16

#define HRT_MAGIC_MMAP_OFFSET (PAGE_SIZE*100)

typedef struct hrt_wnd
{
	int rs;
	int re;
	int cs;
	int ce;
}hrt_wnd;


#define HRT_MAGIC  'x'
#define HRT_START_STREAM _IO(HRT_MAGIC, 0)
#define HRT_STOP_STREAM _IO(HRT_MAGIC, 1)
#define HRT_SET_WND _IOW(HRT_MAGIC,  2, struct hrt_wnd)
#define HRT_GET_WND _IOR(HRT_MAGIC,  3, struct hrt_wnd)
#define HRT_DOWN_USER_COUNT _IO(HRT_MAGIC,  4)
#define HRT_DB_ON _IO(HRT_MAGIC,  5) //Double Buffering ON
#define HRT_DB_OFF _IO(HRT_MAGIC,  6) //Double Buffering OFF
#define HRT_SET_CAPTURE_MODE _IOW(HRT_MAGIC,  7, int)
#define HRT_GET_CAPTURE_MODE _IOR(HRT_MAGIC,  8, int)

-----------------------------16533773738594844211914544919
Content-Disposition: attachment; filename="i2c.h"
Content-Type: application/octet-stream; name=i2c.h
Content-Transfer-Encoding: 7bit

/*
 *
 * Header for I2C constants
 *
 *  Authors: Brett W. Thompson, Gilberto Morejon, Alex Rudnick
 *
 */

/* This is the device's unique ID */
#define HRT_AD_DEVICE_ID (128+16+8+4)

static unsigned char i2c_startcmd[] = { 0, 2, 3, 1, 0 };
static unsigned char i2c_stopcmd[] = { 0, 1, 3, 2, 3 };
static unsigned long i2c_offset = 0x2001;
static int sd = 10;                                                                                                                            

/* Thanks to Dr. Baker for informative comments for each byte */
const unsigned char i2c_datalow[] = {
  0x4c, /* 0x00 - increment delay (IDEL) =  */
  0x3c, /* 0x01 - HSY begin 50 Hz */
  0x0d, /* 0x02 - HSY stop 50 Hz */
  0xef, /* 0x03 - HCL begin 50 Hz */
  0xbd, /* 0x04 - HCL stop 50 Hz */
  0xf0, /* 0x05 - HSY after PHI1 50 Hz */
  0x00, /* 0x06 - luminance control */
  0x00, /* 0x07 - hue control */
  0xf8, /* 0x08 - colour killer threshold QUAM (PAL/NTSC) */
  0xf8, /* 0x09 - colour killer threshold SECAM */
  0x60, /* 0x0A - PAL switch sensitivity */
  0x50, /* 0x0B - SECAM switch sensitivity */
  0x00, /* 0x0C - gain control chrominance */
  0x86, /* 0x0D - standard/mode control */
  /* 7 VTRC = 1  (VCR mode, not TV)
     6 XXX
     5 XXX
     4 XXX
     3 RTSE = 0  (PLIN switched to output)
     2 HRMV = 1  (HREF normal position)
     1 SSTB = 1  (status byte = 1)
     0 SECS = 0  (other standards, not SECAM) */
  0x18, /* 0x0E - I/O and clock control */
  0x90, /* 0x0F - control #1 */
  0x00, /* 0x10 - control #2 */
  0x2c, /* 0x11 - chrominance gain reference */
  0x7f, /* 0x12 - chrominance saturation */
  0x5e, /* 0x13 - luminance contrast */
  0x42, /* 0x14 - HSY begin 60 Hz */
  0x1a, /* 0x15 - HSY stop 60 Hz */
  0xff, /* 0x16 - HCL begin 60 Hz */
  0xda, /* 0x17 - HCL stop 60 Hz */
  0xf0, /* 0x18 - HSY after PHI1 60 Hz */
  0x9b  /* 0x19 - luminance brightness */
};

/* 1A - not used */
/* 1B - not used */
/* 1C - not used */
/* 1D - not used */
/* 1E - not used */
/* 1F - not used */

const unsigned char i2c_datahigh[] = {
  0x7c, /* 0x20 - analog control #1 */
  0x03, /* 0x21 - analog control #2 */
  0xd2, /* 0x22 - mixer control #1 */
  0x41, /* 0x23 - clamping level control 21 */
  0x80, /* 0x24 - clamping level control 22 */
  0x41, /* 0x25 - clamping level control 31 */
  0x80, /* 0x26 - clamping level control 32 */
  0x4f, /* 0x27 - gain control #1*/
  0xfe, /* 0x28 - white peak control*/
  0x01, /* 0x29 - sync bottom control */
  0xcf, /* 0x2A - gain control analog #2 */
  0x0f, /* 0x2B - gain control analog #3 */
  0x83, /* 0x2C - mixer control #2 */
  0x01, /* 0x2D - integration value gain */
  0x81, /* 0x2E - vertical blanking pulse set */
  0x03, /* 0x2F - vertical blanking pulse reset */
  0x60, /* 0x30 - ADCs gain control */
  0x71, /* 0x31 - mixer control #3 */
  0x02, /* 0x32 - integration value white peak */
  0x8c, /* 0x33 - mixer control #4 */
  0x03  /* 0x34 - gain update level */
};


struct i2c_regval {
  int reg;
  unsigned char val;
};
                                                                                                                             
                                                                                                                             
/* I2C routines */

int i2c_busy(unsigned long addr)
{
	int rv;
	rv = !(readb(addr + 0x2000) & 0x80);
	rmb();
	return rv;
}

                                                                                                                             
void i2c_sendstop(unsigned long addr)
{
  int i;
  for (i = 0; i < 5; i++) {
    writeb(i2c_stopcmd[i], i2c_offset + addr);
    wmb();
    udelay(sd);
  }
}
                                                                                                                             
void i2c_sendstart(unsigned long addr)
{
  int i;
  for (i = 0; i < 5; i++) {
    writeb(i2c_startcmd[i], i2c_offset + addr);
    wmb();
    udelay(sd);
  }
}
                                                                                                                             
void i2c_sendbit(unsigned long addr, unsigned char sda)
{
  unsigned long i2c = i2c_offset + addr;
  static int dontfreeze = 0;
  writeb(sda << 1, i2c);
  wmb();
  udelay(sd);
  writeb((sda << 1) + 4, i2c);
  wmb();
                                                                                                                             
  for (;;) {
    if (i2c_busy(addr)) {
                                                                                                                             
      mdelay(1);
      schedule();
      dontfreeze++;
      if (dontfreeze > 10000) break;
    } else {
      break;
    }
  }
  writeb(2, i2c);
  wmb();
  udelay(sd);
}

void i2c_sendbyte(unsigned long addr, unsigned char byte)
{
  int i, sda;
  unsigned char ack;
  unsigned long i2c = i2c_offset + addr;
                                                                                                                             
  for (i = 7; i >= 0; i--) {
    sda = (byte & (1 << i)) >> i;
    i2c_sendbit(addr, sda);
  }
                                                                                                                             
  writeb(3, i2c);
  wmb();
  udelay(sd);
  ack = readb(i2c);
  rmb();
  if ((ack & 2) == 2) {
    printk("<1>Error: no ACK after sending a databyte\n");
  }
  writeb(2, i2c);
  wmb();
}




void init_i2c(unsigned long addr)
{
  int i;
  i2c_sendstop(addr);
  /* Send start command */
  i2c_sendstart(addr);
  /* Send unique A/D address */
  i2c_sendbyte(addr, HRT_AD_DEVICE_ID);
  /* Set device's pointer to 0 */
  i2c_sendbyte(addr, 0);
                                                                                                                             
  for (i = 0; i < 26; i++) {
    i2c_sendbyte(addr, i2c_datalow[i]);
  }
                                                                                                                             
  i2c_sendstop(addr);
  i2c_sendstart(addr);
  i2c_sendbyte(addr, HRT_AD_DEVICE_ID);
                                                                                                                             
  /* Set address pointer = 0x20 */
  i2c_sendbyte(addr, 0x20);
                                                                                                                             
  for (i = 0; i < 21; i++) {
    i2c_sendbyte(addr, i2c_datahigh[i]);
  }
  i2c_sendstop(addr);
}



void shutdown_i2c(unsigned long addr)
{
  int i;
  i2c_sendstop(addr);
  /* Send start command */
  i2c_sendstart(addr);
  /* Send unique A/D address */
  i2c_sendbyte(addr, HRT_AD_DEVICE_ID);
  /* Set device's pointer to 0 */
  i2c_sendbyte(addr, 0);
                                                                                                                             
  for (i = 0; i < 26; i++) {
    i2c_sendbyte(addr, 0);
  }
                                                                                                                             
  i2c_sendstop(addr);
  i2c_sendstart(addr);
  i2c_sendbyte(addr, HRT_AD_DEVICE_ID);
                                                                                                                             
  /* Set address pointer = 0x20 */
  i2c_sendbyte(addr, 0x20);
                                                                                                                             
  for (i = 0; i < 21; i++) {
    i2c_sendbyte(addr, 0);
  }
  i2c_sendstop(addr);
}





                                                                                                                             
/* Set an I2C register */
int i2c_set_reg(unsigned long addr, int reg, unsigned char val)
{
  i2c_sendstart(addr);
  i2c_sendbyte(addr, HRT_AD_DEVICE_ID);
  i2c_sendbyte(addr, reg);
  i2c_sendbyte(addr, val);
  i2c_sendstop(addr);
                                                                                                                             
  return val;
}
                                                                                                                             
int set_brightness(unsigned long addr, unsigned char b)
{
  i2c_set_reg(addr, 0x19, b);
  return b;
}
                                                                                                                             
int set_contrast(unsigned long addr, unsigned char c)
{
  i2c_set_reg(addr, 0x13, c);
  return c;
}


-----------------------------16533773738594844211914544919--
From keith.haynes@earthlink.net  Fri Jun 18 10:06:53 2004
Return-Path: <keith.haynes@earthlink.net>
X-Original-To: baker@cs.fsu.edu
Delivered-To: baker@cs.fsu.edu
Received: from cs.fsu.edu (envoy.cs.fsu.edu [128.186.120.106])
	by mail.cs.fsu.edu (Postfix) with ESMTP id 4B9B7F29B1
	for <baker@cs.fsu.edu>; Fri, 18 Jun 2004 10:06:53 -0400 (EDT)
Received: from falcon.mail.pas.earthlink.net ([207.217.120.74]) by cs.fsu.edu with Microsoft SMTPSVC(6.0.3790.0);
	 Fri, 18 Jun 2004 10:06:53 -0400
Received: from thecount.psp.pas.earthlink.net ([207.217.78.22])
	by falcon.mail.pas.earthlink.net with esmtp (Exim 3.33 #1)
	id 1BbK17-0001lP-00
	for baker@cs.fsu.edu; Fri, 18 Jun 2004 07:06:53 -0700
Message-ID: <1064125.1087567612968.JavaMail.root@thecount.psp.pas.earthlink.net>
Date: Fri, 18 Jun 2004 10:06:51 -0400 (GMT-04:00)
From: Keith Haynes <keith.haynes@earthlink.net>
Reply-To: Keith Haynes <keith.haynes@earthlink.net>
To: baker@cs.fsu.edu
Subject: HRT Driver 2
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary=---------------------------42999170982906996135497281
X-Mailer: Earthlink Zoo Mail 1.0
X-OriginalArrivalTime: 18 Jun 2004 14:06:53.0632 (UTC) FILETIME=[820AAC00:01C4553D]
X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on mail.cs.fsu.edu
X-Spam-Level: 
X-Spam-Status: No, hits=-4.9 required=5.0 tests=BAYES_00,L_TO_ME 
	autolearn=ham version=2.63
Status: RO
Content-Length: 1253
Lines: 57

-----------------------------42999170982906996135497281
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Part 2
-----------------------------42999170982906996135497281
Content-Disposition: attachment; filename="Makefile"
Content-Type: application/octet-stream; name=Makefile
Content-Transfer-Encoding: 7bit

# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y


# This Makefile has been simplified as much as possible, by putting all
# generic material, independent of this specific directory, into
# ../Rules.make. Read that file for details

TOPDIR  := $(shell cd ..; pwd)
include $(TOPDIR)/Rules.make

# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
  DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
else
  DEBFLAGS = -O2
endif

CFLAGS += $(DEBFLAGS)
CFLAGS += -I..

TARGET = grab
OBJS = $(TARGET).o
SRC =  hrt.c

all: .depend $(TARGET).o 


$(TARGET).o: $(SRC:.c=.o)
	$(LD) -r $^ -o $@

install:
	install -d $(INSTALLDIR)
	install -c $(TARGET).o $(INSTALLDIR)

clean:
	rm -f *.o *~ core .depend

depend .depend dep:
	$(CC) $(CFLAGS) -M *.c > $@


ifeq (.depend,$(wildcard .depend))
include .depend
endif

-----------------------------42999170982906996135497281--
