[Top][All Lists]
[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"
+
+
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r4959 - in gnuradio/branches/developers/nldudok1/general-wip: . cxadc,
nldudok1 <=