commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r4959 - in gnuradio/branches/developers/nldudok1/gener


From: nldudok1
Subject: [Commit-gnuradio] r4959 - in gnuradio/branches/developers/nldudok1/general-wip: . cxadc
Date: Wed, 11 Apr 2007 18:39:02 -0600 (MDT)

Author: nldudok1
Date: 2007-04-11 18:39:02 -0600 (Wed, 11 Apr 2007)
New Revision: 4959

Added:
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/Makefile
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxadc.c
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxcap.c
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/i2ctune.c
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/mknod_cxadc.sh
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/readme.txt
   gnuradio/branches/developers/nldudok1/general-wip/cxadc/sdr_readme.txt
Log:
initial checkin of cxadc tv capture card kernel driver for continuous raw 
capturing

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/Makefile
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/Makefile            
                (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/Makefile    
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,36 @@
+
+xyyCFLAGS = -I/usr/src/kernels/2.6.18-1.2798.fc6-i586/include 
-I/usr/src/kernels/2.6.18-1.2798.fc6-i586/include/asm-i386/mach-default
+xxxCFLAGS =  -I/usr/src/kernels/2.6.18-1.2798.fc6-i586/include 
-I/usr/include/asm/mach-default
+
+
+
+UNAME := $(shell uname -r)
+KERNEL26 := 2.6
+KERNELVERSION := $(findstring $(KERNEL26),$(UNAME))
+
+
+ifeq ($(KERNELVERSION),2.6)
+
+obj-m  := cxadc.o
+
+INCLUDE        := -I/usr/include/asm/mach-default/
+KDIR   := /lib/modules/$(shell uname -r)/build
+PWD            := $(shell pwd)
+
+all::
+       $(MAKE) -C $(KDIR) $(INCLUDE) SUBDIRS=$(PWD) modules
+       
+else
+
+TARGET := simplefifo
+INCLUDE        := -I/lib/modules/`uname -r`/build/include 
-I/usr/src/kernels/2.6.18-1.2798.fc6-i586/include/asm-i386/mach-default
+CFLAGS := -O2 -Wall -DMODULE -D__KERNEL__ -DLINUX
+CC     := gcc
+
+all:: ${TARGET}.o
+
+${TARGET}.o: ${TARGET}.c
+       $(CC) $(CFLAGS) ${INCLUDE} -c ${TARGET}.c
+       
+endif
+

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxadc.c
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxadc.c             
                (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxadc.c     
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,1061 @@
+
+/*
+    cxadc - cx2388x adc dma driver for linux 2.6.18
+    version 0.3
+    developed on Fedora Core 6
+
+    uname -a
+    Linux localhost.localdomain 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:54:20 
EDT 2006 i686 i686 i386 GNU/Linux
+
+
+    Copyright (c) 2005-2007 Hew How Chee <address@hidden>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT 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
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+Make sure you log in as super user
+
+To compile     : make
+Output file    : cxadc.ko      
+Create node    : mknod /dev/cxadc c 126 0 
+Install driver : insmod ./cxadc.ko
+
+Run 'cxcap' to capture raw data. See cxcap.c to info on how to compile cxcap
+
+Reference      : btaudio driver, mc4020 driver , cxadc driver v0.2
+       
+*/
+
+/* 'dmesg' log after insmod ./cxadc.ko   (Addresses/Numbers might be different)
+
+If it is not something like this, then there might be memory allocation error.
+
+cxadc: mem addr 0xfd000000 size 0x0
+cxadc: risc inst buff allocated at virt 0xd4f40000 phy 0x14f40000 size 132 
kbytes
+cxadc: total DMA size allocated = 32768 kb
+cxadc: end of risc inst 0xd4f6000c total size 128 kbyte
+cxadc: IRQ used 11
+cxadc: MEM :fd000000 MMIO :d8f80000
+cxadc: dev 0x8800 (rev 5) at 02:0b.0, cxadc: irq: 11, latency: 255, mmio: 
0xfd000000
+cxadc: char dev register ok
+cxadc: audsel = 2
+
+
+*/
+
+/* dmesg log after running cxcap to capture data 
+   note that once cxadc driver is loaded, DMA is always running
+   to stop driver use 'rmmod cxadc'
+
+ 
+cxadc: open [0] private_data c7aa0000
+cxadc: vm end b7f8b000 vm start b5f8b000  size 2000000
+cxadc: vm pg off 0
+cxadc: mmap private data c7aa0000
+cxadc: enable interrupt
+cxadc: release
+
+
+
+*/
+
+
+/*
+  History
+
+  25 sep 2005 - added support for i2c, use i2c.c to tune
+              - set registers to lower gain
+              - set registers so that no signal is nearer to sample value 128
+              - added vmux and audsel as parms during driver loading
+                (for 2nd IF hardware modification, load driver using vmux=2 )
+                By default audsel=2 is to route tv tuner audio signal to
+                audio out of TV card, vmux=1 use the signal from video in of 
tv card.
+                      
+  Feb-Mac 2007 - change code to compile and run in kernel 2.6.18               
+               - clean up mess in version 0.2 code
+               - it still a mess in this code
+  
+
+*/
+
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/moduleparam.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#define cx_read(adr)         readl(ctd->mmio+((adr)>>2))
+#define cx_write(dat,adr)    writel((dat),(ctd->mmio+((adr)>>2)))
+
+
+
+#define CX_SRAM_BASE 0x180000
+#define CX_VIDEO_VBI_CMDS_BASE  (CX_SRAM_BASE+0x100)
+
+
+#define CXADC_IOCTL_WRITE_PLL_REG 0x12345676
+
+/* ------------------------------------------------------------------------- */
+/* CX registers                                                              */
+#define CX_PLL_REG            0x310168 //PLL register
+#define CX_SAMP_RATE_CONV_REG 0x310170 //sample rate conversion register
+#define CX_DEV_CNTRL2          0x200034 //  Device control
+#define CX_VID_INT_STAT        0x200054 //  Video interrupt status
+#define CX_DMA24_PTR1          0x30008C //  DMA Current Ptr : Ch#24_ir
+#define CX_DMA24_PTR2          0x3000CC //  DMA Tab Ptr     : Ch#24
+#define CX_DMA24_CNT1          0x30010C //  DMA Buffer Size : Ch#24
+#define CX_DMA24_CNT2          0x30014C //  DMA Table Size  : Ch#24
+#define CX_VID_DMA_CNTRL               0x31c040 //  Video DMA control
+#define CX_VBI_GP_CNT          0x31C02C //  VBI general purpose counter
+#define VID_CAPTURE_CONTROL    0x310180
+#define CX_PCI_INT_STAT                0x200044
+#define CX_PCI_INT_MSK         0x200040
+
+#define CX_GPIO                 0x350010
+#define CX_GPOE                        0x350014        
+#define CX_PINMUX_IO            0x35c044
+#define CX_GP3_IO               0x35001C
+
+#define CX_I2C_COMP_DATACNTRL   0x368000
+/* ------------------------------------------------------------------------ */
+
+#define RISC_SYNC               0x80000000
+#define RISC_WRITE              0x10000000
+#define RISC_JUMP               0x70000000
+#define RISC_WRITERM            0xB0000000
+#define RISC_WRITECM            0xC0000000
+#define RISC_WRITECR            0xD0000000
+
+
+
+/* ------------------------------------------------------------------------ */
+
+//32 Mbytes VBI DMA BUFF
+#define VBI_DMA_BUFF_SIZE (1024*1024*32) 
+//corresponds to 8192 DMA pages of 4k bytes
+#define MAX_DMA_PAGE (VBI_DMA_BUFF_SIZE/PAGE_SIZE)
+
+
+
+/* -------------------------------------------------------------- */
+
+#define WRITE_INST_PER_PAGE 510 
+// WRITE_INST_PER_PAGE -       1 sync instruction (first page only) followed 
by 510 write instruction and finally a
+//                             1 jmp instruction to next page/reloop  
+//                             this will give 4 + 510*8 +  8 = 4092 bytes, 
which fits into a page
+
+#define NUMBER_OF_WRITE_PER_PAGE 510
+//number of write per page must be even
+//each write risc instruction is 8 byte
+//and the end , there is a jmp to next page which is 8 byte
+//giving a total of 510 * 8 + 8 = 4088
+
+#define CLUSTER_BUFFER_SIZE 2048 
+
+
+#define NUMBER_OF_WRITE_NEEDED (VBI_DMA_BUFF_SIZE/CLUSTER_BUFFER_SIZE)
+#define NUMBER_OF_RISC_PAGE 
((NUMBER_OF_WRITE_NEEDED/NUMBER_OF_WRITE_PER_PAGE)+1+1)
+//+1 page for additional one write page if 
NUMBER_OF_WRITE_NEEDED/NUMBER_OF_WRITE_PER_PAGE is not integer
+//+1 page for first sync and jmp instruction (we used 12 bytes of 4 kbytes 
only)
+
+
+
+
+
+
+
+
+
+
+struct risc_page {
+       struct risc_page * next;
+       char buffer [PAGE_SIZE-sizeof(struct risc_page*)];
+};
+struct cxadc {
+       /* linked list */
+       struct cxadc *next;
+
+       /* device info */
+       int            char_dev;
+       struct pci_dev *pci;
+       unsigned int   irq;
+       unsigned long  mem;
+       unsigned long  *mmio;
+//     unsigned int __iomem * mmio;
+
+       /* locking */
+       int            users;
+       struct semaphore lock;
+
+       
+       unsigned int    risc_inst_buff_size;
+       unsigned long   *risc_inst_virt;
+       dma_addr_t      risc_inst_phy;
+       
+       
+       
+       wait_queue_head_t readQ;
+
+       
+       void *pgvec_virt[MAX_DMA_PAGE+1];
+       void *pgvec_phy[MAX_DMA_PAGE+1];
+
+       unsigned long *pgrisc_virt[NUMBER_OF_RISC_PAGE];
+       unsigned long *pgrisc_phy[NUMBER_OF_RISC_PAGE];
+       struct risc_page *risc_ptr;
+       int newpage;
+};
+
+static struct cxadc *cxadcs  = NULL;
+static unsigned int cxcount      = 0;
+#ifdef METHOD2
+static unsigned long risc_start_phy_addr=0;
+#endif
+/* -------------------------------------------------------------- */
+
+
+
+
+#define NUMBER_OF_CLUSTER_BUFFER 8 
+#define CX_SRAM_BASE 0x180000
+
+#define CDT_BASE               (CX_SRAM_BASE+0x1000)
+#define CLUSTER_BUFFER_BASE    (CX_SRAM_BASE+0x4000)
+#define RISC_BUFFER_BASE        (CX_SRAM_BASE+0x2000)
+#define RISC_INST_QUEUE                (CX_SRAM_BASE+0x800)
+#define CHN24_CMDS_BASE        0x180100
+#define DMA_BUFFER_SIZE (256*1024)
+
+#define CX_VID_INT_MSTAT 0x200058
+#define CX_VID_INT_STAT 0x200054
+#define CX_VID_INT_MSK 0x200050
+#define INTERRUPT_MASK 0x18888
+
+
+static struct pci_device_id cxadc_pci_tbl[] = 
+{
+       {
+               .vendor       = 0x14f1, //conexant
+               .device       = 0x8800, 
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       },
+       {
+       
+       }
+};
+
+static void disable_card(struct cxadc*ctd)
+{
+
+
+       /* turn off all DMA / IRQs */
+               //turn off pci interrupt
+               cx_write(0,CX_PCI_INT_MSK);
+               //turn off interrupt
+               cx_write(0,CX_VID_INT_MSK);
+               cx_write(~(u32)0,CX_VID_INT_STAT);
+               //disable fifo and risc
+               cx_write(0,CX_VID_DMA_CNTRL);
+               //disable risc
+               cx_write(0,CX_DEV_CNTRL2);
+
+}
+
+
+/*
+numbuf   - number of buffer
+buffsize - buffer size in bytes
+buffptr  - CX sram start addr for buffer e.g. 0x182000 as in example pg 2-62 
of CX23880/1/2/3 datasheet
+cdtptr   - CX sram start addr for CDT    e.g. 0x181000 as in example pg 2-62 
of CX23880/1/2/3 datasheet
+*/
+
+
+static void create_cdt_table(struct cxadc *ctd,unsigned int numbuf,unsigned 
int buffsize,unsigned int buffptr,unsigned int cdtptr )
+{
+       int i;
+       unsigned int pp,qq;
+       pp=buffptr;
+       qq=cdtptr;
+       for(i=0;i<numbuf;i++)
+       {
+       
+               //printk("cdtptr [%x]= %x\n",qq,pp);
+               
+               writel(pp,ctd->mmio+(qq>>2));
+               qq+=4;
+               
+               writel(0,ctd->mmio+(qq>>2)); /*not needed but we do it anyway*/
+               qq+=4;
+               
+               writel(0,ctd->mmio+(qq>>2)); /*not needed but we do it anyway*/
+               qq+=4;
+               
+               writel(0,ctd->mmio+(qq>>2)); /*not needed but we do it anyway*/
+               qq+=4;
+               
+               
+               pp+=buffsize;
+               
+       
+                       
+       }
+
+}
+
+static void free_dma_buffer(struct cxadc *ctd)
+{
+       int i;
+       for(i=0;i<MAX_DMA_PAGE;i++)
+       {
+               if(ctd->pgvec_virt[i]) 
+               {
+                       dma_free_coherent(&ctd->pci->dev, 4096, 
ctd->pgvec_virt[i],ctd->pgvec_phy[i]);
+
+               }
+       }
+}
+               
+static int alloc_risc_inst_buffer(struct cxadc *ctd) //used
+{
+       //unsigned long size=
+       
ctd->risc_inst_buff_size=(VBI_DMA_BUFF_SIZE/CLUSTER_BUFFER_SIZE)*8+PAGE_SIZE; 
//add 1 page for sync instruct and jump
+       
ctd->risc_inst_virt=pci_alloc_consistent(ctd->pci,ctd->risc_inst_buff_size,&ctd->risc_inst_phy);
+       if (ctd->risc_inst_virt==NULL)
+               return -ENOMEM;
+       memset(ctd->risc_inst_virt,0,ctd->risc_inst_buff_size);
+       
+       printk("cxadc: risc inst buff allocated at virt 0x%x phy 0x%x size %d 
kbytes\n",
+       ctd->risc_inst_virt,ctd->risc_inst_phy,ctd->risc_inst_buff_size/1024);
+       
+       return 0;
+}
+
+static void free_risc_inst_buffer(struct cxadc *ctd) //used
+{
+       if(ctd->risc_inst_virt!=NULL)
+       
pci_free_consistent(ctd->pci,ctd->risc_inst_buff_size,ctd->risc_inst_virt,ctd->risc_inst_phy);
+}
+static int make_risc_instructions(struct cxadc *ctd)//,unsigned long 
cl_size,unsigned long max_page) //used
+{
+       int i;
+       int irqt;
+       unsigned long loop_addr;
+       unsigned long dma_addr;
+       long *pp=(long *)ctd->risc_inst_virt;
+
+       
+       
+       
+       
+       
+       
+               
+       loop_addr=ctd->risc_inst_phy+4;
+       
+       *pp++=RISC_SYNC|(3<<16);
+       
+       irqt=0;
+       for(i=0;i<MAX_DMA_PAGE;i++)
+       {
+       
+               irqt++; 
+               irqt&=0x1ff;
+               *pp++=RISC_WRITE |CLUSTER_BUFFER_SIZE|(3<<26)|(0<<16);  
+               
+//             dma_addr=virt_to_bus(ctd->pgvec[i]);
+               dma_addr=ctd->pgvec_phy[i];
+               //printk("dma addr %x pgvec %x\n",dma_addr,ctd->pgvec[i]);
+               *pp++=dma_addr;
+               if(i!=MAX_DMA_PAGE-1)
+               {       
+                       
+                       *pp++=RISC_WRITE 
|CLUSTER_BUFFER_SIZE|(((irqt==0)?1:0)<<24)|(3<<26)|(1<<16);    
+                       *pp++=dma_addr+CLUSTER_BUFFER_SIZE;
+                       
+               }
+               else
+               {
+               
+                       *pp++=RISC_WRITE 
|CLUSTER_BUFFER_SIZE|(((irqt==0)?1:0)<<24)|(3<<26)|(3<<16);    //reset cnt to 0
+                       *pp++=dma_addr+CLUSTER_BUFFER_SIZE;
+               
+               }
+               
+       }
+       
+#if 0  
+       //test stop FIFO and RISC
+       *pp++=RISC_WRITECR|1;
+       *pp++=CX_VID_DMA_CNTRL;
+       *pp++=0;
+       *pp++=0xffffffff;
+       //test
+#endif 
+//1<<24 = irq , 11<<16 = cnt
+       *pp++=RISC_JUMP|(0<<24)|(0<<16); //interrupt and increment counter
+       *pp++=loop_addr;
+       
+       printk("cxadc: end of risc inst 0x%x total size %d 
kbyte\n",pp,((unsigned long)pp-(unsigned long)ctd->risc_inst_virt)/1024);
+       return 0;
+
+}
+
+
+
+
+static int cxadc_char_open(struct inode *inode, struct file *file)
+{
+       int minor = iminor(inode);
+       struct cxadc *ctd;
+
+       for (ctd = cxadcs; ctd != NULL; ctd = ctd->next)
+               if (ctd->char_dev == minor)
+                       break;
+       if (NULL == ctd)
+               return -ENODEV;
+
+       //if (debug)
+               printk("cxadc: open [%d] private_data %x\n",minor,ctd);
+       file->private_data = ctd;
+       return 0;
+}
+
+static int cxadc_char_release(struct inode *inode, struct file *file)
+{
+       printk("cxadc: release\n");
+       return 0;
+}
+
+
+static int cxadc_char_ioctl(struct inode *inode, struct file *file,
+                              unsigned int cmd, unsigned long arg)
+{
+       struct cxadc *ctd = file->private_data;
+       int ret=0,val=0;
+//     DECLARE_WAITQUEUE(wait, current);
+       if(cmd==0x12345678)
+       {
+       //      unsigned int i2c;
+               //printk("cxadc : arg %x\n",arg);
+               
+       //      printk("cxadc : i2write 0x%x\n",arg);
+               cx_write(arg&3,CX_I2C_COMP_DATACNTRL);
+               return 0;
+       }
+       if(cmd==CXADC_IOCTL_WRITE_PLL_REG)
+       {
+               cx_write(arg,CX_PLL_REG);
+               printk("cxadc: Set PLL Reg to 0x%x\n",arg);
+               return 0;
+       }
+
+       if(cmd==0x1234567F)
+       {
+               cx_write(0,CX_VBI_GP_CNT);
+               cx_write(1,CX_PCI_INT_MSK); //enable interrupt
+               printk(KERN_INFO "cxadc: enable interrupt\n");
+               return 0;
+       }
+       
+       if(cmd==0x12345677)
+       {
+               
+       //      printk(KERN_INFO "cxadc: wait for data\n");
+       
+               if (file->f_flags & O_NONBLOCK) 
+               {
+                       return  -EAGAIN;
+       
+               }       
+               ctd->newpage=0;
+               wait_event_interruptible(ctd->readQ,ctd->newpage);
+//             printk("wake up new page\n");
+               val=cx_read(CX_VBI_GP_CNT);
+               if (put_user(val, (int *)arg))
+               {
+                       return -EFAULT;
+               }
+               
+       //      printk(KERN_INFO "cxadc: wait for data ok\n");
+               
+               return ret;     
+               
+               
+               //return 0;
+               //add_wait_queue(&ctd->readQ, &wait);
+       }
+       return 0;
+}
+
+
+static struct page *
+cx2388x_vma_nopage (struct vm_area_struct *vma,
+                  unsigned long address, int *type)
+{
+
+       struct cxadc* ctd;
+       struct page *page;
+       unsigned long offset;
+
+
+       if(address<vma->vm_start||address>vma->vm_end)
+       {
+               return NOPAGE_SIGBUS;
+       }
+
+        if (type)
+                *type = VM_FAULT_MINOR;
+
+       offset = (address - vma->vm_start) + vma->vm_pgoff * PAGE_SIZE;
+
+       ctd=vma->vm_private_data;
+       page=virt_to_page(ctd->pgvec_virt[offset>>PAGE_SHIFT]);
+//     printk("cxadc: nopage addr=0x%x pgoff=0x%x %x %x %x 
pgcnt:%d\n",address,vma->vm_pgoff,vma->vm_start,vma->vm_end,offset>>PAGE_SHIFT,page->_count);
 
+       get_page(page);
+       return page;
+    
+
+}
+
+
+
+static struct vm_operations_struct cx2388x_vm_ops = {
+       .nopage = cx2388x_vma_nopage,
+};
+
+
+
+static int cx2388x_mmap (struct file *file, struct vm_area_struct *vma)
+{
+  
+  unsigned long size ; 
+
+  
+   size= (unsigned long) vma->vm_end - vma->vm_start;
+   printk("cxadc: vm end %x vm start %x  size 
%x\n",vma->vm_end,vma->vm_start,size);
+   printk("cxadc: vm pg off %x\n",vma->vm_pgoff);
+    
+#if 1 //added to check param
+       if(vma->vm_pgoff!=0)
+       {
+               printk("cxadc: vm_pgoff !=0\n");
+               return -EINVAL;
+       }
+       if(size>VBI_DMA_BUFF_SIZE)
+       {
+               printk("cxadc: size %u > %u\n",size,VBI_DMA_BUFF_SIZE);
+               return -EINVAL;
+       }
+#endif  
+//???    vma->vm_file = file; //linux-2.6.18.1/drivers/ieee1394/dma.c
+
+  vma->vm_ops = &cx2388x_vm_ops;
+  vma->vm_flags |= VM_RESERVED ;// 
+  vma->vm_private_data = file->private_data;
+  printk("cxadc: mmap private data %x\n",file->private_data);
+  
+  return 0;
+}
+
+static struct file_operations cxadc_char_fops = {
+       .owner    = THIS_MODULE,
+       .llseek   = no_llseek,
+       .open     = cxadc_char_open,
+       .release  = cxadc_char_release,
+       .ioctl    = cxadc_char_ioctl,
+       .mmap     = cx2388x_mmap,
+};
+
+
+
+static char *irq_name[]={
+"Y_RISC_I1","U_RISC_I1","V_RISC_I1","VBI_RISC_I1","Y_RISC_I2","U_RISC_I2","V_RISC_I2","VBI_RISC_I2",
+"YF_OF","UF_OF","VF_OF","VBIF_OF","Y_SYNC","U_SYNC","V_SYNC","VBI_SYNC",
+"OPC_ERR","PAR_ERR","RIP_ERR","PCI_ABORT"};
+static irqreturn_t cxadc_irq(int irq, void *dev_id, struct pt_regs * regs)
+{
+       int count = 0;
+       u32 stat,astat,ostat,allstat;
+       struct cxadc *ctd = dev_id;
+       int handled = 0;
+
+       
+       allstat=cx_read(CX_VID_INT_STAT);
+       stat=cx_read(CX_VID_INT_MSK);
+       astat=stat & allstat;
+       ostat=astat;
+       if(ostat!=8 && allstat!=0 && ostat!=0)
+//     if(ostat)
+       {
+               printk(KERN_INFO "cxadc : Interrupt stat 0x%x Masked 
0x%x\n",allstat,ostat);
+       }
+       //printk("IRQ\n");      
+       //allstat=cx_read(CX_VID_INT_STAT);
+       if(!astat)
+       {
+//             printk(KERN_INFO "cxadc : IRQ not handled\n");
+                return IRQ_RETVAL(handled); //if no interrupt bit set we return
+       }       
+       handled=1;
+       for(count=0;count<20;count++)
+       {
+               
+               if(astat&1)
+               {
+                       if(count==3)
+                       {
+//                             unsigned int uu=cx_read(0x310220);
+//                             printk("%8.8x %x %x %x %x\n",
+//                     uu,uu>>16,(uu>>16)&0x1f,(uu>>8)&0xff,uu&0xff);
+//                     printk("gadj1 %x stip3 %x gadj3 %x gadj4 %x stat %x wc 
%x\n 
",cx_read(0x310214),cx_read(0x310210),cx_read(0x31021c),cx_read(0x310220),cx_read(0x310100),cx_read(0x31011c));
+//                             printk("cxadc: wake up 
%x\n",cx_read(CX_VBI_GP_CNT));
+//                             
+                               ctd->newpage=1;
+                               wake_up_interruptible(&ctd->readQ);
+                       }
+//             printk("IRQ %s\n",irq_name[count]);
+               }
+               astat>>=1;
+       }
+       cx_write(ostat,CX_VID_INT_STAT);
+       /*if(allstat&(~ostat))
+       {
+               printk("IRQ additional %x\n",allstat);
+       }*/
+       
+       return IRQ_RETVAL(handled);
+       
+}
+
+/* -------------------------------------------------------------- */
+
+#define CXADC_MAX 1
+
+static int latency = -1;
+static int audsel=2;
+static int vmux=1;
+
+
+
+static int __devinit cxadc_probe(struct pci_dev *pci_dev,
+                                  const struct pci_device_id *pci_id)
+{
+//     int risc_res;
+       u32 i;
+//     char buffer[256];
+       struct cxadc *ctd;
+//     void *testmalloc;
+       unsigned char revision,lat;
+       int rc;
+       unsigned long total_size;
+       u64 startaddr,pcilen;
+       unsigned int pgsize;
+//printk("cxadc: sizeof(long)=%d sizeof(int)=%d sizeof(long 
int)=%d\n",sizeof(long),sizeof(int),sizeof(long int));     
+//printk("cxadc: no of write needed %d no of risc page 
%d\n",NUMBER_OF_WRITE_NEEDED,NUMBER_OF_RISC_PAGE);
+       
+       if( PAGE_SIZE!=4096)
+       {
+               printk(KERN_ERR "cxadc: only page size of 4096 is supported\n");
+               return -EIO;
+
+       }
+       if (CXADC_MAX == cxcount)
+       {
+               printk(KERN_ERR "cxadc: only 1 card is supported\n");
+               return -EBUSY;
+       }
+
+
+       if (pci_enable_device(pci_dev))
+       {
+               printk(KERN_ERR "cxadc: enable device failed\n");
+               return -EIO;
+       }
+
+       if (!request_mem_region(startaddr=pci_resource_start(pci_dev,0),
+                               pcilen=pci_resource_len(pci_dev,0),
+                               "cxadc")) {
+               printk(KERN_ERR "cxadc: request memory region failed\n");
+               return -EBUSY;
+       }
+       printk(KERN_INFO "cxadc: mem addr 0x%lx size 0x%lx\n",startaddr,pcilen);
+       
+       
+       ctd = kmalloc(sizeof(*ctd),GFP_ATOMIC);
+       if (!ctd) {
+               rc = -ENOMEM;
+               printk(KERN_ERR "cxadc: kmalloc failed\n");
+               goto fail0;
+       }
+       memset(ctd,0,sizeof(*ctd));
+
+       ctd->pci  = pci_dev;
+       ctd->irq  = pci_dev->irq;
+       
+
+
+       
+       if(alloc_risc_inst_buffer(ctd)!=0)
+       {
+               printk(KERN_ERR "cxadc: cannot alloc risc buffer\n");
+               rc=-ENOMEM;
+               goto fail1;
+       }       
+       
+
+       
+       for(i=0;i<(MAX_DMA_PAGE+1);i++)
+       {
+               ctd->pgvec_virt[i]=0;
+               ctd->pgvec_phy[i]=0;
+       }
+       
+       total_size=0;
+       pgsize=4096;
+       
+       for(i=0;i<MAX_DMA_PAGE;i++)
+       {
+               dma_addr_t dma_handle;
+
+               
ctd->pgvec_virt[i]=(void*)dma_alloc_coherent(&ctd->pci->dev,4096,&dma_handle,GFP_KERNEL);
+               if(ctd->pgvec_virt[i]!=0)
+               {
+//                     int j;
+                       ctd->pgvec_phy[i]=dma_handle;
+//if(i<100)
+//{
+//     printk("dma addr %x virtual pgvec %x page =%x 
cnt=%d\n",ctd->pgvec_phy[i],ctd->pgvec_virt[i],virt_to_page 
(ctd->pgvec_virt[i]),virt_to_page (ctd->pgvec_virt[i])->_count);
+//}
+                        total_size+=pgsize;
+               }
+               else
+               {
+                       printk("cxadc: alloc dma buffer failed. index = 
%d\n",i);
+                       rc=-ENOMEM;
+                       goto fail1x;
+               }
+               
+       }
+       
+       printk(KERN_INFO "cxadc: total DMA size allocated = %d 
kb\n",total_size/1024);
+
+       make_risc_instructions(ctd);
+
+               
+       
+       
+       
+       
+       //ctd->pci  = pci_dev;
+       //ctd->irq  = pci_dev->irq;
+       printk("cxadc: IRQ used %d\n",ctd->irq);
+       ctd->mem  = pci_resource_start(pci_dev,0);
+       
+       ctd->mmio = ioremap(pci_resource_start(pci_dev,0),
+                           pci_resource_len(pci_dev,0));
+       printk("cxadc: MEM :%x MMIO :%x\n",ctd->mem,ctd->mmio);
+       //ctd->source     = 1;
+       //ctd->bits       = 8;
+       //ctd->channels   = 1;
+       //printk("btprobe3\n");
+       /* sample rate */
+       //ctd->rate = card->rate;
+       //if (rate[cxcount])
+
+//     ctd->rate = rate[cxcount];
+
+       
+       init_MUTEX(&ctd->lock);
+        //init_waitqueue_head(&ctd->readq);
+       init_waitqueue_head(&ctd->readQ);
+//     printk("cxadc: init waitq %x\n",ctd->readQ);
+       if (-1 != latency) {
+               printk(KERN_INFO "cxadc: setting pci latency timer to %d\n",
+                      latency);
+               pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
+       }
+       else
+       {
+               pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 255);
+       }
+        pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
+        pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
+        printk("cxadc: dev 0x%X (rev %d) at %02x:%02x.%x, ",
+              pci_dev->device,revision,pci_dev->bus->number,
+              PCI_SLOT(pci_dev->devfn),PCI_FUNC(pci_dev->devfn));
+        printk("cxadc: irq: %d, latency: %d, mmio: 0x%lx\n",
+              ctd->irq, lat, ctd->mem);
+       //printk("cxadc: using card config \"%s\"\n", card->name);
+
+       /* init hw */
+
+
+       pci_set_master(pci_dev);
+
+
+       disable_card(ctd);      
+       
+
+
+/* we use 16kbytes of FIFO buffer*/
+       create_cdt_table( ctd, 
NUMBER_OF_CLUSTER_BUFFER,CLUSTER_BUFFER_SIZE,CLUSTER_BUFFER_BASE,CDT_BASE);
+       cx_write((CLUSTER_BUFFER_SIZE/8-1),CX_DMA24_CNT1); /* size of one 
buffer in qword -1 */
+//     printk("cnt1:%x\n",CLUSTER_BUFFER_SIZE/8-1);
+       
+       
+       
+       cx_write(CDT_BASE,CX_DMA24_PTR2); /* ptr to cdt */
+       cx_write(2*NUMBER_OF_CLUSTER_BUFFER,CX_DMA24_CNT2); /* size of cdt in 
qword */
+       
+       
+       
+       
+//     if(ctd->tbuf!=NULL)
+       {
+
+               unsigned int xxx;
+               xxx=cx_read(CX_VID_INT_STAT);
+               cx_write(xxx,CX_VID_INT_STAT); //clear interrupt        
+               
+
+               
+
+               
+               cx_write(ctd->risc_inst_phy,CHN24_CMDS_BASE);//working 
+               cx_write(CDT_BASE,CHN24_CMDS_BASE+4);
+               cx_write(2*NUMBER_OF_CLUSTER_BUFFER,CHN24_CMDS_BASE+8);
+               cx_write(RISC_INST_QUEUE,CHN24_CMDS_BASE+12);
+
+               cx_write(0x40 ,CHN24_CMDS_BASE+16);
+               
+               //source select (see datasheet on how to change adc source)
+               //1<<14 - video in
+               
+               vmux&=3;//default vmux=1
+               cx_write((vmux<<14)|(4<<0),0x310104); //pal-B, yadc =mux1 (<<14)
+               
+               
+               //vbi lenght CLUSTER_BUFFER_SIZE/2  work
+                               
+               cx_write((((CLUSTER_BUFFER_SIZE)<<17)|(2<<11)),0x310188); //no 
of byte transferred from peripehral to fifo
+                                                               // if fifo 
buffer < this, it will still transfer this no of byte
+                                                               //must be 
multiple of 8, if not go haywire?
+               
+               //raw mode & byte swap <<8 (3<<8=swap)
+               cx_write( ((0xe)|(0xe<<4)|(0<<8)) , 0x310184);
+               cx_write(((1<<6)|(3<<1)|(1<<0)),0x310180); //capture 8 bit raw
+               //cx_write(((1<<6)|(3<<1)|(1<<5)),0x310180); //capture 16 bit 
raw
+//             cx_write(((1<<6)),0x310180);
+               //run risc
+//             wmb();
+               cx_write(1<<5,CX_DEV_CNTRL2);
+//             wmb();
+               //enable fifo and risc
+               cx_write(((1<<7)|(1<<3)),CX_VID_DMA_CNTRL);
+//             wmb();
+       
+       //      for(i=0x4000;i<0x8000;i+=4)
+       //      {       
+       //              cx_write(0xaaaaaaaa,(CX_SRAM_BASE+i));
+       //      }       
+               
+               
+                       
+       }
+       
+       
+       
+       
+
+       if ((rc = request_irq(ctd->irq, cxadc_irq, SA_SHIRQ|SA_INTERRUPT,
+                             "cxadc",(void *)ctd)) < 0) {
+               printk(KERN_WARNING
+                      "cxadc: can't request irq (rc=%d)\n",rc);
+               goto fail1x;
+       }
+
+#if 1
+       /* register devices */
+#define CX2388XADC_MAJOR  126                 
+       if (register_chrdev (CX2388XADC_MAJOR, "cxadc", &cxadc_char_fops))
+       {
+               printk (KERN_ERR "cxadc: failed to register device\n");
+               rc=-EIO;
+               goto fail2;
+       }
+       else
+       {
+               printk("cxadc: char dev register ok\n");               
+       }       
+#endif
+
+
+       //set audio multiplexer
+       
+       //set vbi agc
+       cx_write((0<<21)|(0<<20)|(0<<19)|(4<<16)|(0x60<<8)|(0x1c<<0),0x310204);
+                       
+       cx_write((0<<27)|(0<<26) |(1<<25)| (0x100<<16) |(0xfff<<0),   0x310200);
+       
cx_write((1<<23)|(0<<22)|(0<<21)|(0x0a<<16)|(0xff<<8)|(0x0<<0),0x310220);//control
 gain also bit 16
+       cx_write((0x1c0<<17)|(0x0<<9)|(0<<7)|(0xf<<0),0x310208);
+       cx_write((0x20<<17)|(0x0<<9)|(0<<7)|(0x3f<<0),0x31020c);
+//     cx_write((0x1e48<<16)|(0xe0<<8)|(0x40<<0),0x310210);
+       cx_write((0x1e48<<16)|(0xff<<8)|(0x0),0x310210);
+       cx_write((0xe0<<17)|(0xe<<9)|(0x0<<7)|(0x7<<0),0x310214);
+       cx_write((0x28<<16)|(0x28<<8)|(0x50<<0),0x31021c);//set gain of agc but 
not offset
+       
+       //==========Pixelview PlayTVPro Ultracard specific============
+       //select which output is redirected to audio output jack
+       //
+       cx_write(1<<25,CX_GP3_IO); //use as 24 bit GPIO/GPOE 
+       cx_write(0x0b,CX_GPOE); //bit 3 is to enable 4052 , bit 0-1 4052's AB
+       cx_write(audsel&3,CX_GPIO); //3=audio in to audio out
+                                   //2=fm out?
+                                   //1=silence ?
+                                   //0=tuner tv audio out?
+       printk("cxadc: audsel = %d\n",audsel&3);
+       //=================================================
+       
+       //i2c sda/scl set to high and use software control
+       
+       cx_write(3,CX_I2C_COMP_DATACNTRL);
+       //=================================================
+       
+       /* hook into linked list */
+       ctd->next = cxadcs;
+       cxadcs = ctd;
+       cxcount++;
+
+       pci_set_drvdata(pci_dev,ctd);
+       cx_write(INTERRUPT_MASK,CX_VID_INT_MSK);
+       //cx_write(1,CX_PCI_INT_MSK); //enable interrupt
+//     printk("page size %d\n",PAGE_SIZE);
+        return 0;
+
+// fail4:
+       //unregister_sound_dsp(ctd->dsp_analog);
+// fail3:
+       //if (digital)
+       //      unregister_sound_dsp(ctd->dsp_digital);
+ fail2:
+        free_irq(ctd->irq,ctd);        
+ fail1x:
+       free_dma_buffer(ctd);
+       free_risc_inst_buffer(ctd);
+ fail1:
+
+       kfree(ctd);
+
+//     if(ctd->mmio!=NULL) iounmap(ctd->mmio); 
+ fail0:
+
+       release_mem_region(pci_resource_start(pci_dev,0),
+                          pci_resource_len(pci_dev,0));
+       return rc;
+}
+
+static void __devexit cxadc_remove(struct pci_dev *pci_dev)
+{
+       struct cxadc *ctd = pci_get_drvdata(pci_dev);
+       struct cxadc *walk;
+       int i;
+
+       disable_card(ctd);              
+//             wmb();
+       /* unregister devices */
+
+       
+       
+         /* Next, unregister ourselves with the character device driver 
handler */
+  if ((i = unregister_chrdev(CX2388XADC_MAJOR, "cxadc")))
+    printk (KERN_ERR "cxadc: unregister failed, error=%d\n", -i);
+    else
+    printk("cxadc: unregister ok\n");
+
+       
+       /* free resources */
+       free_risc_inst_buffer(ctd);
+        free_irq(ctd->irq,ctd);
+       printk("cxadc: irq freed\n");
+       free_dma_buffer(ctd);
+       printk("cxadc: dma page freed\n");
+//     printk("cxadc: try release mem region\n");
+       iounmap(ctd->mmio);
+       release_mem_region(pci_resource_start(pci_dev,0),
+                          pci_resource_len(pci_dev,0));
+       printk("cxadc: release mem region ok\n");
+       /* remove from linked list */
+       if (ctd == cxadcs) {
+               cxadcs = NULL;
+       } else {
+               for (walk = cxadcs; walk->next != ctd; walk = walk->next)
+                       ; /* if (NULL == walk->next) BUG(); */
+               walk->next = ctd->next;
+       }
+       cxcount--;
+       printk("cxadc: reset drv data\n");
+       pci_set_drvdata(pci_dev, NULL);
+       printk("cxadc: reset drv ok\n");
+       kfree(ctd);
+       printk("cxadc: end\n");
+       return;
+}
+/* -------------------------------------------------------------- */
+/*
+
+
+
+*/
+static struct pci_driver cxadc_pci_driver = {
+        .name     = "cxadc",
+        .id_table = cxadc_pci_tbl,
+        .probe    = cxadc_probe,
+        .remove   = __devexit_p(cxadc_remove),
+};
+
+
+static int cxadc_init_module(void)
+{
+       return pci_module_init(&cxadc_pci_driver);
+}
+
+static void cxadc_cleanup_module(void)
+{
+       pci_unregister_driver(&cxadc_pci_driver);
+       return;
+}
+
+
+module_init(cxadc_init_module);
+module_exit(cxadc_cleanup_module);
+
+
+module_param(latency,         int, 0644);
+module_param(audsel,         int, 0644);
+module_param(vmux,         int, 0644);
+//audsel=2 is taken from tuner stereo out ?
+//vmux=2 is taken from 2nd IF (after hardware mod)
+//vmux=1 is taken from video in
+
+
+MODULE_DEVICE_TABLE(pci, cxadc_pci_tbl);
+MODULE_DESCRIPTION("cx2388xx adc driver");
+MODULE_AUTHOR("Hew How Chee");
+MODULE_LICENSE("GPL");

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxcap.c
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxcap.c             
                (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/cxcap.c     
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,198 @@
+
+/*
+       cxcap.c  version 0.3 is to be used with cxadc.c driver to capture 
+       raw data from cx2388x TV tuner cards 
+         
+    Copyright (c) 2005 Hew How Chee <address@hidden>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT 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
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+/*
+
+ 
+ The output is stored in raw.pcm as unsigned 8 bit data
+ 
+ To compile : gcc cxcap.c -o cxcap
+ To run     : ./cxcap
+ 
+ Make sure to read instructions in cxadc.c on creating /dev/cxadc inode
+
+  History
+
+  4 sep 2005 - bug fix when NPAGE set to more than 8192
+             - rewrite capture loop
+  Feb 2007   - change code to write to file direct instead
+               of writing to memory first
+
+*/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <memory.h>
+
+
+//MAX_PAGE value should be same as MAX_DMA_PAGE in cxadc.c. Do not change
+#define MAX_PAGE 8192   
+
+
+char  rawbuff[1024*4];
+
+
+void help()
+{
+       printf("\ncxcap [file size kb] [filename]\n");
+       printf("default  : file size = 8 Mbyte , filename = raw.pcm\n");
+       printf("sampling rate = 27 MHz. File format is 8 bit unsigned\n");
+        printf("e.g.\n");
+       printf("cxcap 200               to capture 200 Mbyte file\n");
+        printf("cxcap 100 sample.pcm    to capture 100 Mbyte file called 
sample.pcm\n");
+        
+    
+}
+int  main(int argc,char *argv[])
+
+{      
+       //int jj;
+       int fd0,i;
+       int total_page=2048; //default to 2048 pages of 4 k
+       char *def_file="raw.pcm";
+       char *fname=def_file;
+       FILE *fp1;
+
+       char *mapptr,*buffptr;
+       //unsigned long size;
+       int end_page,npage;
+       //int diffp;
+       int start_page,sync;//MAX_PAGE-1;
+//     float srate;
+//     unsigned int pllreg=-1;
+
+       if(argc>1)
+       {
+               float mbyte;
+               
+               sscanf(argv[1],"%f",&mbyte);
+               total_page=(mbyte*1024.0*1024.0/4096.0)+1;
+               if(total_page<0) 
+               {
+                       printf("Invalid total page %d\n",total_page);
+                       return -1;
+               }
+               printf("total page to write = %d (approx %f 
MByte)\n",total_page,(float)total_page*4096.0/1024.0/1024.0);
+       }
+       else
+       {
+               help();
+               printf("\nNo arguments specified. Capturing %d page (%f Mbyte) 
to raw.pcm\n",total_page, total_page*4096.0/1024.0/1024.0);
+
+       }
+       if(argc>2)
+       {
+               fname=argv[2];
+               
+       }
+       
+       fp1=fopen(fname,"wb+"); 
+       printf("file = %s\n",fname);
+       
+       if(fp1==NULL)
+       {
+               printf("file open error\n");
+               //close(fd0);
+               return  -1;
+       }
+
+       
+       
+       fd0 = open ("/dev/cxadc", O_RDWR);
+       if (fd0 < 0)
+       {       
+               fclose(fp1);
+               printf ("/dev/cxadc open error\n");
+               return -1;
+       }
+       
+
+//map cxadc circular buffer to user space
+       mapptr=mmap(0,1024*1024*32,PROT_READ|PROT_WRITE,MAP_SHARED,fd0,0x000);
+       
+       ioctl (fd0, 0x1234567f,0); //enable interrupt
+
+
+       npage=0;
+       start_page=0;
+       sync=1;
+//     buffptr=rawbuff;
+       while(1)
+       {
+
+               
+               
+               do
+               {
+                       ioctl (fd0, 0x12345677, &end_page); //wait for new data
+                       end_page&=(MAX_PAGE-1);
+                       
+               
+               } while((end_page>0x220||end_page<0x1e0)&&sync);//wait until 
things stabilized and ptr is at beginning of
+                                                                               
                                //cxadc circular buffer
+
+               if(sync) printf("\ncapturing data.\n"); 
+               sync=0;
+       
+        
+ 
+                printf("ok  0x%x 0x%x\n",start_page,end_page);
+        
+               while(start_page!=end_page)
+               {
+#if 0
+//copy to our memory first and write
+
+                       
memcpy(rawbuff,mapptr+(start_page*4096),sizeof(rawbuff));
+                       fwrite(rawbuff,sizeof(rawbuff),1,fp1);
+
+#else  //we write direct to file 
+                       fwrite(mapptr+(start_page*4096),sizeof(rawbuff),1,fp1);
+#endif
+
+
+
+                       start_page=(start_page+1)&(MAX_PAGE-1);
+                       npage++;
+
+                       if(npage>=total_page) break;
+               
+               }
+               if(npage>=total_page) break;
+
+        
+        
+        
+        
+        
+       }
+        
+       
+       fclose(fp1);
+
+       close(fd0);
+       return 0;
+
+}

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/i2ctune.c
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/i2ctune.c           
                (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/i2ctune.c   
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,219 @@
+/*
+       i2ctune.c  version 0.1 is to be used with cxadc.c driver to 
+       tune tv tuner 
+         
+    Copyright (c) 2005 Hew How Chee <address@hidden>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT 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
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+/*
+History
+
+    20 Sep 2005 - initial code
+                - generally can tune the tuner
+               - but have problem sometimes after band switching
+               - if keyed in frequency  does not seem to tune
+               - try keying in 500 (for 500 Mhz) and go back to that
+               - frequency again 
+
+*/
+
+#include        <stdio.h>
+#include        <signal.h>
+#include        <locale.h>
+#include        <unistd.h>
+#include        <limits.h>
+#include        <stdlib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+//scl is bit 1 , sda is bit 0
+
+
+//fm freq 87.7  88.5  89.3  90.3  91.1 92.3  93.9   95.8  97.2   ...
+
+#define WAIT100MS  {usleep(100000);}
+#define WAIT10MS  {usleep(10000);}
+
+#define SCL_HIGH {state|=2;setio(state,fd0);}
+#define SCL_LOW  {state&=1;setio(state,fd0);}
+#define SDA_HIGH {state|=1;setio(state,fd0);}
+#define SDA_LOW  {state&=2;setio(state,fd0);}
+
+
+void setio(unsigned int x,int dev)
+{
+       ioctl(dev,0x12345678,x);
+}
+void send4byte(unsigned int x,int swap)
+{
+       int fd0;
+
+       unsigned char data[5];
+       unsigned int state=3;
+       unsigned char sft;
+       int i,j;
+//     FILE *fp;
+//     fp=fopen("C:\\i2c.pcm","wb+");
+
+       fd0 = open ("/dev/cxadc", O_RDWR);
+       if (fd0 < 0)
+       {       
+               printf ("open error");
+               return ;
+       }
+       data[0]=0xc0;
+//     swap=1;
+       if(!swap)
+       {
+               printf("not swap\n");
+               data[1]=(x>>24)&0xff;
+               data[2]=(x>>16)&0xff;
+               data[3]=(x>>8)&0xff;
+               data[4]=(x)&0xff;
+       }
+       else
+       {
+               printf("swap\n");
+               data[3]=(x>>24)&0xff;
+               data[4]=(x>>16)&0xff;
+               data[1]=(x>>8)&0xff;
+               data[2]=(x)&0xff;
+       }
+
+       //idle
+       SCL_HIGH
+       SDA_HIGH
+       //SETIO
+       WAIT100MS
+       //start
+       SDA_LOW
+       //SETIO
+       WAIT10MS
+       for(i=0;i<5;i++)
+       {
+               sft=data[i];
+               for(j=0;j<8;j++)
+               {
+                       SCL_LOW
+       //              SETIO
+                       WAIT10MS
+                       if(sft&0x80)
+                       {
+                               SDA_HIGH
+                       }
+                       else
+                       {
+                               SDA_LOW
+                       }
+       //              SETIO
+                       WAIT10MS
+                       SCL_HIGH
+       //              SETIO
+                       WAIT10MS
+                       sft<<=1;
+
+
+               }
+               SCL_LOW
+       //      SETIO
+               WAIT10MS
+               //ack
+               SDA_HIGH
+               WAIT10MS
+               SCL_HIGH
+       //      SETIO
+               WAIT10MS
+
+
+
+       }
+       SCL_LOW
+       //SETIO
+       WAIT10MS
+       SDA_LOW
+       //SETIO
+       WAIT10MS
+       SCL_HIGH
+       WAIT10MS
+       SDA_HIGH
+       WAIT10MS
+       close(fd0);
+       
+//     fclose(fp);     
+}
+int main()
+{
+
+       unsigned int val;
+       float ifreq,freq=48.3;
+       float oldfreq=-1.0;
+       int swap=0;
+       while(1)
+       {
+               printf("\nEnter radio station in Mhz (e.g. 87.7) :");
+               scanf("%f",&freq);
+               if((freq<48.25)||(freq >863.25)) 
+               {
+                       freq=87.7;
+                       printf("freq out of range. default to 87.7\n");
+               }
+
+               //oldfreq=freq;
+               ifreq=freq+10.7;
+               ifreq*=20;
+               val=ifreq+0.5;
+               printf("val %d\n",val);
+               val&=0xffff;
+               val<<=16;
+               //val|=0x88a6;
+               val|=0x8800;
+               if(freq<170) val|=0xa6;
+               else if(freq>=170 && freq<=470) val|=0x96;
+               else val|=0x36;
+               
+               if(oldfreq==-1)
+               {
+                       swap=0;
+                       
+               }
+               else
+               {
+                       if(freq>oldfreq)
+                       {
+                               swap=0;
+                       }
+                       else
+                       {
+                               swap=1;
+                       }
+               }
+               
+               oldfreq=freq;
+
+               printf("sending 0x%x %d 
%f\n",val,val>>16,((float)(val>>16))/20.0-10.7);
+               send4byte(val,swap);
+               //usleep(300000);
+               //freq=oldfreq;
+               ///freq+=.5;
+//             usleep(500000);
+               freq+=0.1;
+       }
+       return 0;
+
+}

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/mknod_cxadc.sh
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/mknod_cxadc.sh      
                        (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/mknod_cxadc.sh      
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,2 @@
+#!/bin/sh
+mknod /dev/cxadc c 126 0


Property changes on: 
gnuradio/branches/developers/nldudok1/general-wip/cxadc/mknod_cxadc.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/readme.txt
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/readme.txt          
                (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/readme.txt  
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,74 @@
+Notes for cxadc.c and cxcap.c  24 Mac 2007 
+==========================================
+
+The purpose of these program is to get continuous  8 bit ADC raw data from 
+the CX2388x based TV cards. TV tuner functions are not supported. Register to 
+initialized sampling rate is not used. By default, after reset, sampling rate 
is
+27 Mhz.
+
+These program are developed on Fedora Core 6. (kernel 2.6.18)
+
+
+cxadc.c is the driver for CX2388x TV card
+cxcap.c is the program and get the raw data from the driver and store it into 
file.
+
+These codes are a bit messy since I have no time to clean up. It might contain 
bugs
+but at least it runs (on my machine).
+
+Quick procedure to get it running (capture from video in of card)
+=================================================================
+
+Instruction may be specific to PixelView PlayTV Pro Ultra TV card
+
+WARNING : Before trying, make sure you have backup your important data
+just in case.
+
+a) copy cxadc.c and cxcap.c to a new folder on the hard disk (mounted r/w)
+
+b) run 'make' to compile cxadc.c
+
+c) to compile cxcap, type in
+
+       gcc cxcap.c -o cxcap
+
+d) create device node with the following command. (make sure you are super 
user)
+
+       mknod /dev/cxadc c 126 0
+
+e) install driver
+
+       insmod ./cxadc.ko
+
+f) check 'dmesg' output to see whether it is similiar to the one
+   shown in the cxadc.c source code
+
+g) If it is ok, run cxcap to capture 8Mbyte of raw data. The signal source is 
feed into the
+   video input of the CX2388x tv card. 
+
+        ./cxcap
+
+h) Check 'dmesg' output to see the result similiar to one shown in cxadc.c
+
+i) The output is saved in raw.pcm as 8 bit unsigned.
+
+j) stop the driver by using the command
+
+       rmmod cxadc
+
+k) to get another capture , repeat e), g), and j). 
+   (note this step might not be necessary but for the mean time, we'll
+    just stop and start the driver again to be safe).
+   
+   note : after installing driver, DMA is always running. To stop DMA, you 
need to remove driver
+          if you don't stop, you can run cxcap to capture again.
+    
+
+These codes runs are meant for Intel 32 bit single processor only. My machine 
is a Dell Pentium III
+800 MHz PC.
+
+Version 0.2 or higher of the driver let you set the ADC input source during 
driver loading. Use "vmux=X"  to do this,
+X=0 to 3
+
+
+Hew How Chee
address@hidden

Added: gnuradio/branches/developers/nldudok1/general-wip/cxadc/sdr_readme.txt
===================================================================
--- gnuradio/branches/developers/nldudok1/general-wip/cxadc/sdr_readme.txt      
                        (rev 0)
+++ gnuradio/branches/developers/nldudok1/general-wip/cxadc/sdr_readme.txt      
2007-04-12 00:39:02 UTC (rev 4959)
@@ -0,0 +1,41 @@
+With hardware modification, it is possible to get 2nd IF of TV/FM tuner into 
the CX2388x
+ADC. In our case, we set the tuner to FM mode. This will cause the IF to be 
taken
+from after a 10.7Mhz filter. 
+
+i2ctune.c can be used to tune to a desired radio station. If PixelView PlayTV 
Pro Ultra
+TV/FM card is used, the audio can be heard if you plug a speaker into the 
audio out of
+the card.
+
+Run cxcap.c to capture 8 bit unsigned raw sample of the 10.7 Mhz IF. Samples 
are stored
+in raw.pcm.  
+
+NOTE also i2ctune.c sometimes does not work when frequency band switching is 
involved.
+If this happen, try to tune to 500 Mhz and back to your FM radio station 
frequency again.
+
+Procedure (after code has been compiled). TV card is PixelView PlayTV Pro Ultra
+========================================
+
+a) mknod /dev/cxadc c 126 0
+
+d) insmod ./cxadc.o vmux=2    (specific to our hardware modifications)
+
+e) check 'dmesg' output to see whether it is similiar to the one
+   shown in the cxadc.c source code
+
+f) run i2ctune
+
+g) key in radio station frequency. If a speaker is connected to tv card audio 
out,
+   station should be heard. If not try note above.
+
+h) quit i2ctune by pressing ctrl-c. 
+
+f) run 'cxcap 200' to capture 200 Mbyte of 8 bit unsigned data to raw.pcm
+
+g) Check 'dmesg' output to see the result similiar to one shown in cxadc.c
+
+h) The output is saved in raw.pcm as 8 bit unsigned.
+
+i) stop the driver by using the command "rmmod cxadc"
+
+   
+





reply via email to

[Prev in Thread] Current Thread [Next in Thread]