📄 vportdis.c
字号:
(params->cbDefVal << 16) | (params->crDefVal << 24);
chan->resmpl = params->resmpl;
chan->scale = params->scale;
numPixels >>= params->scale;
chan->numPixels = numPixels;
numCPixels = (params->dmode & _VPORT_MASK_RAW) ? 0 : numPixels >> 1;
if(params->dmode & _VPORT_MASK_RAW) { /* raw mode */
chan->cPitch = 0;
if(params->dmode == VPORT_MODE_RAW_8BIT) {
chan->yPitch = (numPixels + 7) & (~ 7);
chan->cPitch = (numCPixels + 7) & (~ 7);
} else if(params->dmode == VPORT_MODE_RAW_10BIT) {
if(params->bpk10Bit == VPORTDIS_BPK_10BIT_DENSE){
chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
}else {
chan->yPitch = (numPixels * 2 + 7) & (~ 7);
}
} else if(params->dmode == VPORT_MODE_RAW_16BIT) {
chan->yPitch = (numPixels * 2 + 7) & (~ 7);
} else {
chan->yPitch = (numPixels * 4 + 7) & (~ 7);
}
} else {
if(params->dmode & _VPORT_MASK_10BIT) {
if(params->bpk10Bit == VPORTDIS_BPK_10BIT_DENSE){
chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
chan->cPitch = (numCPixels* 4 / 3 + 7) & (~ 7);
}else {
chan->yPitch = (numPixels * 2 + 7) & (~ 7);
chan->cPitch = (numCPixels * 2 + 7) & (~ 7);
}
} else {/* 8 bit mode */
chan->yPitch = (numPixels + 7) & (~ 7);
chan->cPitch = (numCPixels + 7) & (~ 7);
}
}
chan->yThrld = params->thrld;
if(params->mergeFlds && params->fldOp == VPORT_FLDOP_FRAME) {
/* frame capture and merge 2 fields into one frame */
/* make sure threshold is same as line size */
chan->yThrld = chan->yPitch >> 3;
chan->numEventsFld1 = chan->numLinesFld1;
chan->numEvents = chan->numLines;
chan->mergeFlds = TRUE;
}else {
/* these two asserts make sure that total transfer sizes of */
/* both the whole frame and the first field are multiples */
/* of the threshold */
assert(((chan->yPitch*chan->numLinesFld1)/(chan->yThrld << 3))
*(chan->yThrld << 3) == (chan->yPitch*chan->numLinesFld1));
assert(((chan->yPitch*chan->numLines)/(chan->yThrld << 3))
*(chan->yThrld << 3) == (chan->yPitch*chan->numLines));
chan->numEventsFld1 =
chan->yPitch * chan->numLinesFld1 / (chan->yThrld << 3);
chan->numEvents =
chan->yPitch * chan->numLines / (chan->yThrld << 3);
chan->mergeFlds = FALSE;
}
if(params->dmode & _VPORT_MASK_RAW) {
chan->cThrld = 0;
}
else {
chan->cThrld = (chan->yThrld + 1) >> 1;
}
base[_VP_VDTHRLD_OFFSET] =
VP_VDTHRLD_RMK(chan->yThrld,params->incPix,chan->yThrld);
base[_VP_VDDISPEVT_OFFSET] =
VP_VDDISPEVT_RMK((chan->numEvents-chan->numEventsFld1),
chan->numEventsFld1 );
chan->mode = params->dmode;
chan->status |= _VPORT_CFGED;
}
return IOM_COMPLETED;
}
/*
* ======== displayEdmaISR ========
*/
Int frame = 0;
Int totalFrame = 0;
static void displayEdmaISR(tcc)
{
Int i;
FVID_Frame *viop, *curViop;
/* find out the source of the edma interrupt */
for(i = 0; i < _VP_PORT_CNT; i ++) {
_VPORT_ChanObj* chan = &chanObjs[i];
if((chan->status & _VPORT_READY) && tcc == chan->tcc[0]){
totalFrame ++;
/* make sure all transfers are completed */
if(!(chan->mode & _VPORT_MASK_RAW)) {
while(! EDMA_intTest(chan->tcc[1]));
EDMA_intClear(chan->tcc[1]);
while(! EDMA_intTest(chan->tcc[2]));
EDMA_intClear(chan->tcc[2]);
}
if(chan->mergeFlds){
/* 1st field is being captured, update */
/* the rld to point to the 2nd field */
/* of the current frame, which is the nextViop */
EDMA_RSETH(chan->hEdma[0], SRC,
chan->nextViop->frame.iFrm.y1);
EDMA_RSETH(chan->hRld[0], SRC,
chan->nextViop->frame.iFrm.y1);
EDMA_RSETH(chan->hRld[1], SRC,
chan->nextViop->frame.iFrm.y2);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hEdma[1], SRC,
chan->nextViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hEdma[2], SRC,
chan->nextViop->frame.iFrm.cr1);
EDMA_RSETH(chan->hRld[2], SRC,
chan->nextViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[4], SRC,
chan->nextViop->frame.iFrm.cr1);
EDMA_RSETH(chan->hRld[3], SRC,
chan->nextViop->frame.iFrm.cb2);
EDMA_RSETH(chan->hRld[5], SRC,
chan->nextViop->frame.iFrm.cr2);
}
}/*if(chan->mergeFlds){*/
/* update the reload address */
curViop = chan->curViop;
chan->curViop = chan->nextViop;
if((viop = (FVID_Frame *)QUE_dequeue(&chan->qIn))
!= (FVID_Frame *)&chan->qIn) {
/* queue IS not empty */
chan->nextViop = viop;
}else {
chan->queEmpty = TRUE;
}
if(!chan->mergeFlds) {
EDMA_RSETH(chan->hRld[0], SRC,
chan->nextViop->frame.iFrm.y1);
if(! (chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[1], SRC,
chan->nextViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[2], SRC,
chan->nextViop->frame.iFrm.cr1);
}
}/* if(!chan->mergeFlds) {*/
if(curViop != chan->curViop) {
if(chan->packetIOM != INV) {
/* call the channel's callback function */
*(void **)chan->packetIOM->addr = curViop;
chan->packetIOM->size = sizeof(FVID_Frame);
chan->cbFxn((Ptr)chan->cbArg, chan->packetIOM);
chan->packetIOM = INV;
}else {
QUE_enqueue(&chan->qOut,curViop);
}
}/*if(curViop != chan->curViop) {*/
else {
frame ++;
}
}/*if((chan->status & READY) && tcc == chan->tcc[0]){*/
} /*for(i = 0; i <_VP_PORT_CNT; i++) { */
}
/*
* ======== displayISR ========
*/
static void displayISR(int portNum)
{
volatile Int *base =
(volatile Int *)chanObjs[portNum].base;
Int vpis = base[_VP_VPIS_OFFSET];
Int mask = vpis & chanObjs[portNum].vIntMask;
if(mask && chanObjs[portNum].vIntFxn != INV) {
chanObjs[portNum].vIntFxn(chanObjs[portNum].cbArg, mask);
}
/* clear interrupts that has been handled */
base[_VP_VPIS_OFFSET] |= vpis;
}
/*
* ======== _displayStart ========
* start video display
*/
static Int _displayStart(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
/* enable port and display */
base[_VP_VPCTL_OFFSET] |= VP_VPCTL_VPHLT_CLEAR << _VP_VPCTL_VPHLT_SHIFT;
base[_VP_VDCTL_OFFSET] |= VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT;
/* wait for display counters and control signals to sync up */
TSK_sleep(100);
base[_VP_VDCTL_OFFSET] &= ~ (_VP_VDCTL_BLKDIS_MASK);
/* enable interrupt */
base[_VP_VPIE_OFFSET] |= VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT;
IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
IRQ_enable(IRQ_EVT_VINT0 + chan->portNum);
return IOM_COMPLETED;
}
/*
* ======== _displayStop ========
* stop video display
*/
static Int _displayStop(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
base[_VP_VDCTL_OFFSET] &= ~ (VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT);
return IOM_COMPLETED;
}
/*
* ======== _dundRecover ========
* force recover from display under-run
*/
static Int _dundRecover(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
Int i;
volatile Int* base = (volatile Int *)chan->base;
/* disable under run interrupt */
base[_VP_VPIE_OFFSET] &= ~ (_VP_VPIE_DUND_MASK);
/* clear any pending under-run interrupt */
base[_VP_VPIS_OFFSET] &= ~ (_VP_VPIS_DUND_MASK);
/* block display events */
base[_VP_VDCTL_OFFSET] |= _VP_VDCTL_BLKDIS_MASK;
/* Disable the edmas before settings them up */
EDMA_disableChannel(chan->hEdma[1]);
EDMA_clearChannel(chan->hEdma[1]);
EDMA_disableChannel(chan->hEdma[2]);
EDMA_clearChannel(chan->hEdma[2]);
EDMA_intDisable(chan->tcc[0]);
EDMA_disableChannel(chan->hEdma[0]);
EDMA_clearChannel(chan->hEdma[0]);
/* set up DMA parameters again */
EDMA_RSETH(chan->hEdma[0], SRC, chan->curViop->frame.iFrm.y1);
EDMA_RSETH(chan->hEdma[0], CNT, EDMA_CNT_RMK(chan->numEvents - 1,
chan->yThrld << 1));
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hEdma[1], SRC, chan->curViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hEdma[2], SRC, chan->curViop->frame.iFrm.cr1);
EDMA_RSETH(chan->hEdma[1], CNT,
EDMA_CNT_RMK(chan->numEvents - 1, chan->cThrld << 1));
EDMA_RSETH(chan->hEdma[2], CNT,
EDMA_CNT_RMK(chan->numEvents - 1, chan->cThrld << 1));
}
/* enable the edma events again before settings them up */
EDMA_enableChannel(chan->hEdma[1]);
EDMA_enableChannel(chan->hEdma[2]);
EDMA_intEnable(chan->tcc[0]);
EDMA_enableChannel(chan->hEdma[0]);
base[_VP_VDCTL_OFFSET] |= VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT;
for(i = 0; i < 10000; i ++);
base[_VP_VDCTL_OFFSET] &= ~(_VP_VDCTL_BLKDIS_MASK);
/* re-enable under run interrupt */
base[_VP_VPIE_OFFSET] |= _VP_VPIE_DUND_MASK;
return IOM_COMPLETED;
}
/*
* ======== _setVIntCb ========
* set video port interrutp call-back
*/
static Int _setVIntCb(Ptr chanp, Ptr args)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
VPORT_VIntCbParams* vIntCbParams = (void *)args;
Int mask = vIntCbParams->vIntMask;
Uns vif2 = 0, vInt2 = 0, vif1 = 0, vInt1 = 0;
chan->vIntMask = mask;
/* check to see if vertical interrupt is enabled */
if(mask |= VPORT_INT_VINT1) {
vif1 = 1;
vInt1 = vIntCbParams->vIntLine;
}
if(mask |= VPORT_INT_VINT2) {
vif2 = 1;
vInt2 = vIntCbParams->vIntLine;
}
base[_VP_VDVINT_OFFSET] = VP_VDVINT_RMK(vif2,
vInt2, vif1, vInt1);
if(mask) {
mask |= 1; /* turn on video port interrupt */
IRQ_map(IRQ_EVT_VINT0 + chan->portNum, vIntCbParams->irqId);
HWI_dispatchPlug(vIntCbParams->irqId, (Fxn)displayISR, -1, NULL);
IRQ_disable(IRQ_EVT_VINT0 + chan->portNum);
IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
}
base[_VP_VPIE_OFFSET] |= mask; /* register write */
chan->vIntFxn = vIntCbParams->vIntCbFxn;
return IOM_COMPLETED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -