📄 vportcap.c
字号:
chan->numEvents =
chan->yPitch * chan->numLines / (chan->yThrld << 3);
if(params->fldOp != VPORT_FLDOP_FRAME) {
chan->interlaced = FALSE;
}
}
chan->mergeFlds = params->mergeFlds;
chan->cThrld = (chan->yThrld + 1) >> 1;
base[_VP_VCAEVTCT_OFFSETA] = VP_VCAEVTCT_RMK(
(chan->numEvents-chan->numEventsFld1), chan->numEventsFld1 );
base[_VP_VCATHRLD_OFFSETA] = VP_VCATHRLD_RMK(chan->yThrld,chan->yThrld);
} else { /* raw capture */
VPORTCAP_ParamsRaw *paramsRaw = (VPORTCAP_ParamsRaw *)params;
Int totalNumPixels = paramsRaw->lineSz * paramsRaw->numLines;
Int totalBytesPerFrame;
/* make sure the number is in the correct range */
assert(totalNumPixels < 2^24);
/* configure channel A capture settings */
vcCtl = VP_VCACTL_RMK(0, 1, 0, 0, 0, 0, 0, 0, 0,
paramsRaw->bpk10Bit, 0, 0, 0, 0, 1, 0,0, 0, paramsRaw->cmode);
/* reset channel */
base[_VP_VCACTL_OFFSETA] |=
VP_VCACTL_RSTCH_RESET << _VP_VCACTL_RSTCH_SHIFT;
_delay(2000);
base[_VP_VCACTL_OFFSETA] = vcCtl;
base[_VP_VCASTRT1_OFFSETA]
= VP_VCASTRT1_RMK(1, paramsRaw->startupSyncEnable,
paramsRaw->blankperiod);
base[_VP_VCASTOP1_OFFSETA]
= VP_VCASTOP1_RMK((totalNumPixels >> 12), (totalNumPixels & 0xFFF));
chan->resmpl = FALSE;
chan->scale = FALSE;
if( paramsRaw->cmode == VPORT_MODE_RAW_16BIT ) {
totalBytesPerFrame = paramsRaw->lineSz * 2 * paramsRaw->numLines;
} else if(paramsRaw->cmode == VPORT_MODE_RAW_20BIT) {
totalBytesPerFrame = paramsRaw->lineSz * 4 * paramsRaw->numLines;
} else if(paramsRaw->cmode == VPORT_MODE_RAW_10BIT){
if( paramsRaw->bpk10Bit == VPORTCAP_BPK_10BIT_ZERO_EXTENDED
|| paramsRaw->bpk10Bit == VPORTCAP_BPK_10BIT_SIGN_EXTENDED){
/* each 10-bit pixel takes 2 bytes */
totalBytesPerFrame = paramsRaw->lineSz * 2 * paramsRaw->numLines;
} else { /* dense packing, 3 10-bit pixel takes 4 bytes */
/* make sure this is dividable */
assert((paramsRaw->lineSz * paramsRaw->numLines / 3) * 3 ==
paramsRaw->lineSz * paramsRaw->numLines );
totalBytesPerFrame = paramsRaw->lineSz * 4 * paramsRaw->numLines / 3;
}
} else { /* 8-bit raw mode */
totalBytesPerFrame = paramsRaw->lineSz * paramsRaw->numLines;
}
chan->yPitch = paramsRaw->thrld << 3;
chan->cPitch = 0;
chan->yThrld = paramsRaw->thrld;
chan->interlaced = FALSE;
chan->mergeFlds = FALSE;
chan->cThrld = 0;
assert(totalBytesPerFrame / chan->yPitch * chan->yPitch == totalBytesPerFrame);
chan->numLines = totalBytesPerFrame / chan->yPitch;
chan->numEvents = chan->numLines;
base[_VP_VCATHRLD_OFFSETA] = VP_VCATHRLD_RMK(chan->yThrld,chan->yThrld);
} /* if(!(chan->mode & _VPORT_MASK_RAW)) */
chan->status|=_VPORT_CFGED;
retVal = IOM_COMPLETED;
}
return retVal;
}
/*
* ======== _configChan ========
* configure channel settings
*/
static Int _configChan(Ptr chanp, Ptr args)
{
VPORTCAP_Params* params = (VPORTCAP_Params*)args;
/* configure video port channel A/B control register */
_configCh(chanp, params);
/* configure EDMA and frame buffer */
_configTransfer(chanp, params);
return IOM_COMPLETED;
}
/*
* ======== _configPort ========
* configure port level registers
*/
static Int _configPort(Ptr chanp, Ptr args)
{
PortObj* port = (PortObj *)chanp;
volatile Int *base = (volatile Int *)port->base;
/* configure video port control register */
VPORT_PortParams* portParams = (VPORT_PortParams*)args;
/* enable video port */
base[_VP_PCR_OFFSET] |= VP_PCR_PEREN_ENABLE << _VP_PCR_PEREN_SHIFT;
/* reset video port */
base[_VP_VPCTL_OFFSET] |=
VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT;
while(base[_VP_VPCTL_OFFSET] & (VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT));
base[_VP_VPCTL_OFFSET] = VP_VPCTL_RMK(0,0,0,portParams->vc3Polarity,
portParams->vc2Polarity,portParams->vc1Polarity,0,0,
portParams->dualChanEnable);
/* enable video port */
base[_VP_VPCTL_OFFSET] |= (VP_VPCTL_VPHLT_CLEAR << _VP_VPCTL_VPHLT_SHIFT);
port->chanObj[0].edcFxns = portParams->edcTbl[0];
port->chanObj[1].edcFxns = portParams->edcTbl[1];
IRQ_clear(IRQ_EVT_EDMAINT);
return IOM_COMPLETED;
}
/*
* ======== _configTransfer ========
* configure channel EDMA settings
*/
static Int _configTransfer(
Ptr chanp,
VPORTCAP_Params *params
)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
Int i;
EDMA_Config cfgEdma;
Int thrld;
Int8* curAddr;
Int numEdmaChans;
VPORTCAP_ParamsRaw *paramsRaw = (VPORTCAP_ParamsRaw *)params;
Int numFrmBufs;
Int segId;
Int alignment;
Int irqId;
Int edmaPri;
if(!(params->cmode & _VPORT_MASK_RAW)) {
numFrmBufs = params->numFrmBufs;
segId = params->segId;
alignment = params->alignment;
irqId = params->irqId;
edmaPri = params->edmaPri;
} else {
numFrmBufs = paramsRaw->numFrmBufs;
segId = paramsRaw->segId;
alignment = paramsRaw->alignment;
irqId = paramsRaw->irqId;
edmaPri = paramsRaw->edmaPri;
}
if(chan->status & _VPORT_CFGED) {
assert(numFrmBufs >= 2 && numFrmBufs
<= VPORT_MAX_NUM_FRMBUFS);
QUE_new(&chan->qIn);
chan->queEmpty = FALSE;
chan->mrViop = INV;
chan->packetIOM = INV;
chan->segId = segId;
EDMA_intDisable(chan->tcc[0]);
EDMA_intDisable(chan->tcc[1]);
if(chan->numFrms == 0) {
chan->numFrms = numFrmBufs;
/* allocate frame buffer */
chan->bufSz = chan->yPitch * chan->numLines
+ chan->cPitch * chan->numLines * 2;
for(i = 0; i < chan->numFrms; i ++) {
if((curAddr = MEM_calloc(segId,chan->bufSz,
alignment)) == MEM_ILLEGAL){
return IOM_EALLOC;
}
/* field 1 */
chan->viops[i].frame.iFrm.y1 = curAddr;
if(!(params->cmode & _VPORT_MASK_RAW)) {
curAddr += chan->numLines*chan->yPitch;
chan->viops[i].frame.iFrm.cb1 = curAddr;
curAddr += chan->numLines*chan->cPitch;
chan->viops[i].frame.iFrm.cr1 = curAddr;
curAddr += chan->numLines*chan->cPitch;
/* field 2 */
if(params->fldOp == VPORT_FLDOP_FLD2) {
chan->viops[i].frame.iFrm.y2 =
chan->viops[i].frame.iFrm.y1;
chan->viops[i].frame.iFrm.cb2 =
chan->viops[i].frame.iFrm.cb1;
chan->viops[i].frame.iFrm.cr2 =
chan->viops[i].frame.iFrm.cr1;
}
else if(! chan->mergeFlds) {
chan->viops[i].frame.iFrm.y2 =
chan->viops[i].frame.iFrm.y1
+ chan->numLinesFld1*chan->yPitch;
chan->viops[i].frame.iFrm.cb2 =
chan->viops[i].frame.iFrm.cb1
+ (chan->numLinesFld1*chan->cPitch);
chan->viops[i].frame.iFrm.cr2 =
chan->viops[i].frame.iFrm.cr1
+ (chan->numLinesFld1*chan->cPitch);
}else {
chan->viops[i].frame.iFrm.y2 =
chan->viops[i].frame.iFrm.y1 + chan->yPitch;
chan->viops[i].frame.iFrm.cb2 =
chan->viops[i].frame.iFrm.cb1 + chan->cPitch;
chan->viops[i].frame.iFrm.cr2 =
chan->viops[i].frame.iFrm.cr1 + chan->cPitch;
}
}
}
}
for(i = 2; i < chan->numFrms; i ++) {
/* don't put the first 2 viop into the queue */
QUE_enqueue(&chan->qIn, (QUE_Handle)&chan->viops[i]);
}
chan->curViop = &chan->viops[0];
chan->nextViop = &chan->viops[1];
if(chan->mode & _VPORT_MASK_RAW) {
numEdmaChans = 1;
} else {
numEdmaChans = _VPORT_NUM_EDMA_CHANS;
}
for(i = 0; i < numEdmaChans; i ++) {
Int optFld1 = EDMA_OPT_RMK(
edmaPri,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_YES,
EDMA_OPT_DUM_INC,
EDMA_OPT_TCINT_NO,
EDMA_OPT_TCC_OF(0),
EDMA_OPT_TCCM_OF(0),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_DEFAULT,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
);
Int optFld2a = EDMA_OPT_RMK(
edmaPri,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_YES,
EDMA_OPT_DUM_INC,
(i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),
EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[0] & 0x0f : 0),
EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[0] >> 4 : 0),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_DEFAULT,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
);
Int optFld2b = EDMA_OPT_RMK(
edmaPri,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_YES,
EDMA_OPT_DUM_INC,
(i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),
EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[1] & 0x0f : 0),
EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[1] >> 4 : 0),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_DEFAULT,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
);
thrld = (i == 0) ? chan->yThrld : chan->cThrld;
cfgEdma.src = EDMA_SRC_RMK(chan->edmaAddr[i]);
if(chan->interlaced) {
/* to merge the two fields together */
/* EDMA is configured to transfer only field 1 initially */
/* line pitch is twice the line size */
/* this requires that the threlhold is the same as line size */
/* first field */
cfgEdma.cnt =
EDMA_CNT_RMK((chan->numEventsFld1) - 1, (thrld << 1));
if(chan->mergeFlds) {
cfgEdma.idx = EDMA_IDX_RMK(thrld << 4, 0);
} else {
cfgEdma.idx = EDMA_IDX_RMK(thrld << 3, 0);
}
/* hard code the first two frames as current and reload buffers */
/* first field */
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 1]);
cfgEdma.opt = optFld1;
cfgEdma.dst =
EDMA_DST_RMK(*((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
EDMA_config(chan->hEdma[i], &cfgEdma);
EDMA_config(chan->hRld[4 * i], &cfgEdma);
cfgEdma.dst =
EDMA_DST_RMK(*((Int *)(&chan->viops[1].frame.iFrm.y1) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 3]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -