⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copy of vportcap.c

📁 dm642_video_stream
💻 C
📖 第 1 页 / 共 4 页
字号:
                and idx = 88 * 8 * 2 = 1408;
                
                thrld is different for y and cb/cr.*/
                cfgEdma.idx = EDMA_IDX_RMK(thrld << 4, 0);
    
                /* hard code the first two frames as current and reload buffers */  
                /*  hRld[4*i] 	  - frame A field 1; link to hRld[4*i + 1]
                	hRld[4*i + 1] - frame A field 2; link to hRld[4*i + 2]
                	hRld[4*i + 2] - frame B field 1; link to hRld[4*i + 3]
                	hRld[4*i + 3] - frame B field 2; link to hRld[4*i]  */
                              
                /* first field */
                cfgEdma.opt = optFld1;     
                
                /*get the start address for y/cb/cr respectively base on i*/  
                /*first frame*/
                cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[0].frame.iFrm.y1) + i));
                cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 1]);
                EDMA_config(pChan->hEdma[i], &cfgEdma);
                EDMA_config(pChan->hRld[4 * i], &cfgEdma);  
                /*second frame*/
                cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[1].frame.iFrm.y1) + i));
                cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 3]);
                EDMA_config(pChan->hRld[4 * i + 2], &cfgEdma);

                /* second field */
                cfgEdma.cnt = EDMA_CNT_RMK((pChan->numEvents - pChan->numEventsFld1) - 1, 
                   							(thrld << 1));
                
                /*first frame*/
                cfgEdma.opt = optFld2a;
                cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[0].frame.iFrm.y2) + i));
                cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 2]);
                EDMA_config(pChan->hRld[4 * i + 1], &cfgEdma); 
                
                /*second frame*/
                cfgEdma.opt = optFld2b;
                cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[1].frame.iFrm.y2) + i));
                cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i]);
                EDMA_config(pChan->hRld[4 * i + 3], &cfgEdma);
                
            }
            else 
            {/* if fields are not merged, configure EDMA to transfer */
                   /* for both field1 and field 2                          */
                   /* the line pitch is just the line size                 */
                cfgEdma.opt = optFld2a;
                cfgEdma.cnt = EDMA_CNT_RMK((pChan->numEvents) - 1, (thrld << 1));
                cfgEdma.idx = EDMA_IDX_RMK(thrld << 3, 0);
                cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 2]);
                /* hard code the first and second frame buffer as current  */
                /* and reload buffers */
                cfgEdma.dst = EDMA_DST_RMK(
                    *((Int *)(&pChan->viops[0].frame.iFrm.y1) + i));
                EDMA_config(pChan->hEdma[i], &cfgEdma);
                EDMA_config(pChan->hRld[4 * i], &cfgEdma);

                cfgEdma.opt = optFld2b;
                cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i]);
                cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[1].frame.iFrm.y1) + i));
                EDMA_config(pChan->hRld[4 * i + 2], &cfgEdma);
            }
        }
        pChan->nextEDMARlds = 1;        
        /* enable EDMA channel */
        /*
         * The EDMA interrupt dispatcher will be called by the
         * BIOS HWI interrupt dispatcher.
         */
        IRQ_map(IRQ_EVT_EDMAINT, params->irqId);
        HWI_dispatchPlug(params->irqId, (Fxn)EDMA_intDispatcher, -1, NULL); 
        //HWI_dispatchPlug(params->irqId, (Fxn)IsrForEDMA, -1, NULL);
        
        EDMA_intClear(pChan->tcc[0]);
        EDMA_intHook(pChan->tcc[0], captureEdmaISR);       
        EDMA_intEnable(pChan->tcc[0]);
        EDMA_intClear(pChan->tcc[1]);
        EDMA_intHook(pChan->tcc[1], captureEdmaISR);       
        EDMA_intEnable(pChan->tcc[1]);
        for(i = 0; i < _VPORT_NUM_EDMA_CHANS; i ++) 
        {
            EDMA_disableChannel(pChan->hEdma[i]);
            EDMA_clearChannel(pChan->hEdma[i]);
            EDMA_enableChannel(pChan->hEdma[i]);
        }    
        
        pChan->status |= _VPORT_READY;
        IRQ_enable(IRQ_EVT_EDMAINT);
    }     
    
    return IOM_COMPLETED;
}

/*
 *  ======== _covrRecover ========
 *  force recover from FIFO over-run
 */
static Int _covrRecover(Ptr chanp)
{
    _VPORT_ChanObj *pChan = (_VPORT_ChanObj*)chanp;
    PortObj *pPort = &gsPortObjs[pChan->portNum];
    volatile Int *base = (volatile Int*)pPort->base;
    volatile Int *chBase = (volatile Int*)pChan->base;    
    Int numEvents;
    volatile Int i;                                            
    
    
    /* disable over-run interrupt */
    base[_VP_VPIE_OFFSET] &= ~(_VP_VPIE_COVRA_MASK<<(pChan->chanNum*16));

	/* block capture events */
	if (pChan->chanNum == 0)
        chBase[_VP_VCACTL_OFFSETA] |= _VP_VCACTL_BLKCAP_MASK;
	else if (pChan->chanNum == 1)
		chBase[_VP_VCBCTL_OFFSETB] |= _VP_VCBCTL_BLKCAP_MASK;

    /* Disable the edmas before settings them up */
    EDMA_intDisable(pChan->tcc[0]);
    EDMA_intDisable(pChan->tcc[1]);
    for (i=0; i<_VPORT_NUM_EDMA_CHANS; i++) 
    {
        EDMA_disableChannel(pChan->hEdma[i]);
        EDMA_clearChannel(pChan->hEdma[i]);
    }
/*
    if (pChan->mergeFlds) 
    {
        numEvents = pChan->numEventsFld1;        
    } 
    else 
    {
        numEvents = pChan->numEvents;
    }*/
	if (pChan->mergeFlds) 
        numEvents = pChan->numEvents;        
    else 
        numEvents = pChan->numEventsFld1;
    
    /* set up DMA parameters again */
    EDMA_RSETH(pChan->hEdma[0], DST, pChan->curViop->frame.iFrm.y1);
    EDMA_RSETH(pChan->hEdma[1], DST, pChan->curViop->frame.iFrm.cb1);
    EDMA_RSETH(pChan->hEdma[2], DST, pChan->curViop->frame.iFrm.cr1);
    EDMA_RSETH(pChan->hEdma[0], CNT, EDMA_CNT_RMK(numEvents-1, (pChan->yThrld<<1)) );
    EDMA_RSETH(pChan->hEdma[1], CNT, EDMA_CNT_RMK(numEvents-1, (pChan->cThrld<<1)) );
    EDMA_RSETH(pChan->hEdma[2], CNT, EDMA_CNT_RMK(numEvents-1, (pChan->cThrld<<1)) );

    /* enable the edma events again before settings them up */
    EDMA_intEnable(pChan->tcc[0]);
    EDMA_intEnable(pChan->tcc[1]);
    
    for (i=0; i<_VPORT_NUM_EDMA_CHANS; i++) 
        EDMA_enableChannel(pChan->hEdma[i]);
    
    /* delay */
    for (i = 0; i < 100000; i ++);

    
    if (pChan->chanNum == 0) 
	{
		/* clear any pending over-run interrupt */
        base[_VP_VPIS_OFFSET] |= _VP_VPIS_COVRA_MASK;

		/* enable event generation */
	    chBase[_VP_VCACTL_OFFSETA] &= ~(_VP_VCACTL_BLKCAP_MASK);

		/* enable over-run interrupt */
    	base[_VP_VPIE_OFFSET] |= _VP_VPIE_COVRA_MASK << (pChan->chanNum * 16);
	}
    else if (pChan->chanNum == 1) 
	{
		/* clear any pending over-run interrupt */
        base[_VP_VPIS_OFFSET] |= _VP_VPIS_COVRB_MASK;
        
		/* enable event generation */
	    chBase[_VP_VCBCTL_OFFSETB] &= ~(_VP_VCBCTL_BLKCAP_MASK);

		/* enable over-run interrupt */
    	base[_VP_VPIE_OFFSET] |= _VP_VPIE_COVRB_MASK << (pChan->chanNum * 16);
    }

    return IOM_COMPLETED;
}


/*
 *  ======== _setVIntCb ========
 *  setup video port interrupt call-back
 */
static Int _setVIntCb(Ptr chanp, Ptr args)
{      
    _VPORT_ChanObj *pChan = (_VPORT_ChanObj* )chanp;
    PortObj *pPort = &gsPortObjs[pChan->portNum];
    volatile Int *portBase = (volatile Int *)pPort->base;
    volatile Int *chBase = (volatile Int *)pChan->base;
    VPORT_VIntCbParams *pvIntCbParams = (void *)args;
    
    /* for either channel A or B*/
    Int mask = pvIntCbParams->vIntMask;
    Uns vif2 = 0, vInt2 = 0, vif1 = 0, vInt1 = 0, fscl2 = 0;
    
    /* check to see if vertical interrupt is enabled */
    if(mask & VPORT_INT_VINT1) 
    {
        vif1 = 1;
        vInt1 = pvIntCbParams->vIntLine;
    }
    
    if(mask & VPORT_INT_VINT2) 
    {
        vif2 = 1;
        vInt2 = pvIntCbParams->vIntLine;    
    }
    
    fscl2 = vif2 & (~ vif1);
    
    /* setup vertical interrupt */
    if (pChan->chanNum == 0)
    {/* channel A */
    	chBase[_VP_VCAVINT_OFFSETA] = VP_VCAVINT_RMK(vif2,fscl2, 
        	vInt2, vif1, vInt1); 
	}
	else
	{/* channel B */
        chBase[_VP_VCBVINT_OFFSETB] = VP_VCBVINT_RMK(vif2,fscl2, 
        	vInt2, vif1, vInt1); 
        mask <<= 16;    
    }  
    
    pChan->vIntMask = mask;  
    
    if(mask) 
    {
        mask |= 1; /* turn on video port interrupt */
        IRQ_map(IRQ_EVT_VINT0 + pChan->portNum, pvIntCbParams->irqId);    
        HWI_dispatchPlug(pvIntCbParams->irqId, (Fxn)captureISR, -1, NULL);
        IRQ_disable(IRQ_EVT_VINT0 + pChan->portNum);
        IRQ_clear(IRQ_EVT_VINT0 + pChan->portNum);
    }  
    
    portBase[_VP_VPIE_OFFSET] |= mask;  /* register write */    
    pChan->vIntFxn = pvIntCbParams->vIntCbFxn;    
    pChan->vIntCbArg = pvIntCbParams->cbArg;
    return IOM_COMPLETED;   
}  
    
/*
 *  ======== _startVPCapture ========
 *  start video port capture operation
 */
static Int _startVPCapture(Ptr chanp)
{
    _VPORT_ChanObj *pChan = (_VPORT_ChanObj*)chanp;
    PortObj *pPort = &gsPortObjs[pChan->portNum];
    volatile Int *portBase = (volatile Int*)pPort->base;
    volatile Int *chBase = (volatile Int*)pChan->base;    
                         
	if (pChan->chanNum == 0)
	{
	    /* enable channel A*/
	    chBase[_VP_VCACTL_OFFSETA] |= VP_VCACTL_VCEN_ENABLE << _VP_VCACTL_VCEN_SHIFT;
	
	    _delay(20000000);
	    /* clear the block capture event mask bit to enable */
	    /* generating capture events                        */
	    chBase[_VP_VCACTL_OFFSETA] &= ~ (_VP_VCACTL_BLKCAP_MASK);    
	}
	else
	{
	    /* enable channel B*/
	    chBase[_VP_VCBCTL_OFFSETB] |= VP_VCBCTL_VCEN_ENABLE << _VP_VCBCTL_VCEN_SHIFT;
	
	    _delay(20000000);
	    /* clear the block capture event mask bit to enable */
	    /* generating capture events                        */
	    chBase[_VP_VCBCTL_OFFSETB] &= ~ (_VP_VCBCTL_BLKCAP_MASK);
	}

    /* enable interrupt generation in video port level */
    portBase[_VP_VPIE_OFFSET] |= VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT;
    portBase[_VP_VPIS_OFFSET] |= 0XFFFFFFFF;
    /* clear any pending video port interrupt */
    IRQ_clear(IRQ_EVT_VINT0 + pChan->portNum);
    /* enable corresponding video port interrupt in chip-level*/
    IRQ_enable(IRQ_EVT_VINT0 + pChan->portNum); 
    
    EDMA_intClear(pChan->tcc[0]);
    EDMA_intEnable(pChan->tcc[0]);
    EDMA_intClear(pChan->tcc[1]);
    EDMA_intEnable(pChan->tcc[1]);
    
    return IOM_COMPLETED;
}

/*
 *  ======== _stopVPCapture ========
 *  stop video port capture operation
 */
static Int _stopVPCapture(Ptr chanp)
{
    _VPORT_ChanObj *pChan = (_VPORT_ChanObj* )chanp;
    PortObj *pPort = &gsPortObjs[pChan->portNum];
    volatile Int *chBase = (volatile Int *)pChan->base;    
    volatile Int *portBase = (volatile Int *)pPort->base;  

    /* block events generation */
    if (pChan->chanNum == 0)
    {    
    	/* enable channel A*/
	    chBase[_VP_VCACTL_OFFSETA] |= (_VP_VCACTL_BLKCAP_MASK);
	
	    /* disable channel */
	    chBase[_VP_VCACTL_OFFSETA] &= 
	        ~ (VP_VCACTL_VCEN_ENABLE << _VP_VCACTL_VCEN_SHIFT);
	}  
	else
	{
	     /* enable channel B*/
	    chBase[_VP_VCBCTL_OFFSETB] |= (_VP_VCBCTL_BLKCAP_MASK);
	
	    /* disable channel */
	    chBase[_VP_VCBCTL_OFFSETB] &= 
	        ~ (VP_VCBCTL_VCEN_ENABLE << _VP_VCBCTL_VCEN_SHIFT);
	}
	
    /* disable interrupt generation in video port level */
    portBase[_VP_VPIE_OFFSET] &= ~ (VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT);
    portBase[_VP_VPIS_OFFSET] |= 0XFFFFFFFF;
    
    /* disble corresponding video port interrupt in chip-level*/
    IRQ_disable(IRQ_EVT_VINT0 + pChan->portNum);

    /* clear any pending video port interrupt */
    IRQ_clear(IRQ_EVT_VINT0 + pChan->portNum);
    
    EDMA_intDisable(pChan->tcc[0]);
    EDMA_intClear(pChan->tcc[0]);

    EDMA_intDisable(pChan->tcc[1]);
    EDMA_intClear(pChan->tcc[1]);
    
    pChan->numFrms = 0;
    
	return IOM_COMPLETED;
}



/*
 *  ======== captureISR ========
 */
static void captureISR(Int portNum)
{
    volatile Int *base = (volatile Int*)gsPortObjs[portNum].base;
    Int vpis = base[_VP_VPIS_OFFSET];
    Int mask = vpis;
    _VPORT_ChanObj *chanObjs = gsPortObjs[portNum].chanObj;
        
    if(vpis & chanObjs[0].vIntMask && chanObjs[0].vIntFxn != INV) 
    {
        chanObjs[0].vIntFxn(chanObjs[0].vIntCbArg, vpis);
        mask &=  chanObjs[0].vIntMask;
    }  
    else if(vpis & chanObjs[1].vIntMask && chanObjs[1].vIntFxn != INV) 
    {
        chanObjs[1].vIntFxn(chanObjs[1].vIntCbArg, (vpis >> 16));
        mask &=  chanObjs[1].vIntMask;
    }  
    
    /* clear interrupts that has been handled */
    base[_VP_VPIS_OFFSET] |= mask;
}

static void _autoSync(_VPORT_ChanObj *pChan) 
{
    volatile Int *chBase = (volatile Int*)pChan->base;    
	volatile Int fid_stat;
    volatile Int ypos;
	Int offset = pChan->nextEDMARlds << 1;
	        
    if (pChan->chanNum == 0)
    { 
      	fid_stat = (chBase[_VP_VCASTAT_OFFSETA]&_VP_VCASTAT_VCFLD_MASK) >> _VP_VCASTAT_VCFLD_SHIFT;
		ypos = (chBase[_VP_VCASTAT_OFFSETA]&_VP_VCASTAT_VCYPOS_MASK) >> _VP_VCASTAT_VCYPOS_SHIFT;
	}
	else if (pChan->chanNum == 1)
	{
		fid_stat = (chBase[_VP_VCBSTAT_OFFSETB]&_VP_VCBSTAT_VCFLD_MASK) >> _VP_VCBSTAT_VCFLD_SHIFT;
		ypos = (chBase[_VP_VCBSTAT_OFFSETB]&_VP_VCBSTAT_VCYPOS_MASK) >> _VP_VCBSTAT_VCYPOS_SHIFT;
	}

    if (pChan->interlaced && ( fid_stat == 0 && ypos >= pChan->numTotalLinesFld1
      || fid_stat == 1 && ypos <= pChan->numLinesFld1))
    {
        /* Reconfig the EDMA to link to field 0 of the current transfer */
        EDMA_link(pChan->hEdma[0], pChan->hRld[offset]);
        EDMA_link(pChan->hEdma[1], pChan->hRld[offset+4]);
        EDMA_link(pChan->hEdma[2], pChan->hRld[offset+8]);
    } 
}

static void _delay(Int delayTime)
{
    asm("loop1: BDEC loop1, A4");
    asm(" NOP 5");

}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -