hi
I'm dealing with OV3640 driver on WINCE6.0 platform, the OV3640 module works well now, the out data format is YUV422.
I set OMAP3530's ISP&CCDC register in the driver ,but i can only get a blurred screen,with which fills only a quarter of
the top csreen. I do not know why
.
BOOL CIspCtrl::CCDCConfigSize(ULONG width,ULONG height){
ISP_OutReg32(&m_pCCDCRegs->CCDC_HSIZE_OFF, (width*2)&ISP_32B_BOUNDARY_OFFSET); ISP_OutReg32(&m_pCCDCRegs->CCDC_SDOFST, 0x0); /* Set the horizontal info */ ISP_OutReg32(&m_pCCDCRegs->CCDC_HORZ_INFO, (0<< ISPCCDC_HORZ_INFO_SPH_SHIFT)|((width-1) << 0)); ISP_OutReg32(&m_pCCDCRegs->CCDC_VERT_START, 0<< ISPCCDC_VERT_START_SLV0_SHIFT); /* Set the vertical lines */ ISP_OutReg32(&m_pCCDCRegs->CCDC_VERT_LINES, (height-1) << ISPCCDC_VERT_LINES_NLV_SHIFT);
ISP_OutReg32(&m_pCCDCRegs->CCDC_VDINT, ((height-1)<<ISPCCDC_VDINT_0_SHIFT)); return TRUE; }
void set_ISP()
{
int setting =0;
setting |= ( ISPCTRL_CCDC_CLK_EN //Enable CCDC Clock | ISPCTRL_CCDC_RAM_EN //Use CCDC Ram#if RSZ_ENABLE | ISPCTRL_RSZ_CLK_EN#endif | (ISPCTRL_SYNC_DETECT_VSFALL << ISPCTRL_SYNC_DETECT_SHIFT)| ISPCTRL_CCDC_FLUSH //CCDC memory flush#if RSZ_ENABLE | ISPCTRL_SBL_WR0_RAM_EN //SBL module WRITE0 RAM enable // | ISPCTRL_SBL_WR1_RAM_EN //Used by all module#else | ISPCTRL_SBL_WR1_RAM_EN //Used by all module#endif| (ISPCTRL_PAR_SER_CLK_SEL_parallel)); //parallel interface
setting |=ISPCTRL_SHIFT_2;//wangwj_cam ISP_OutReg32(&m_pIspConfigRegs->CTRL, setting); }
BOOL CIspCtrl::CCDCInitSYNC(){ DEBUGMSG(ZONE_FUNCTION, (TEXT("+CCDCInitSYNC\r\n"))); UINT32 syn_mode = 0 ; #if RSZ_ENABLE syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ; // Video data to resizer #else syn_mode |= ISPCCDC_SYN_MODE_WEN; // Video data to memory syn_mode |= ISPCCDC_SYN_MODE_VDHDEN; // Enable timing generator#endif syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8; syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8; //Set input mode:Interlanced, YCbCr 8
ISP_OutReg32(&m_pCCDCRegs->CCDC_SYN_MODE, syn_mode);
return TRUE; }
BOOL CIspCtrl::CCDCInitCFG(){ DEBUGMSG(ZONE_FUNCTION, (TEXT("+CCDCInitCFG\r\n"))); // Request Init. UINT32 setting = 0 ; ISP_InReg32(&m_pCCDCRegs->CCDC_CFG, &setting); setting |= (ISPCCDC_CFG_VDLC //Enalbe Latching,OMAP Must Set!!! | ISPCCDC_CFG_Y8POS //Even or odd ); //maybe need Y8POS ISP_OutReg32(&m_pCCDCRegs->CCDC_CFG, setting); // This is sensor specific BLC value for Omnivision 3640 OUTREG32(&m_pCCDCRegs->CCDC_DCSUB, 0x10);//turn light low DEBUGMSG(ZONE_FUNCTION, (TEXT("-CCDCInitCFG\r\n"))); return TRUE; }
+CCDCInit,width = 640, height=480+CCDCInitCFG-CCDCInitCFG+CCDCInitSYNC+ISPConfigSize, width =640 ,height =480-CCDCInitISP_SYSCONFIG =0x1001ISP_CTRL =0x98140TCTRL_CTRL =0x9ISP_IRQ0ENABLE =0x0CCDC_SYN_MODE =0x32700CCDC_PCR =0x0CCDC_HORZ_INFO =0x27fCCDC_VERT_START =0x0CCDC_VERT_LINES =0x1dfCCDC_CFG =0x8000CCDC_HORZ_INFO =0x27fCCDC_VERT_START =0x0CCDC_HSIZE_OFF =0x500CCDC_SDOFST =0x0CCDC_SDR_ADDR =0x869ee000CCDC_VDINT =0x1df0000CCDC_ALAW =0x4CCDC_FMTCFG =0x4000CCDC_FMT_HORZ =0x0CCDC_FMT_VERT =0x0CCDC_VP_OUT =0x0RSZ_PCR =0x4RSZ_CNT =0x3fcffRSZ_OUT_SIZE =0x0RSZ_IN_START =0x0RSZ_IN_SIZE =0x0RSZ_SDR_OUTADD =0x0RSZ_SDR_OUTOFF =0x0
Hi xiao,
On seeing the attached image, it looks like either data format does not match in sensor module and OMAP side or data line at the interface between OV3640 and OMAP is not configured as per hardware.
You can verify the following bits.
ISP_CTRL.IRQ0ENABLE is zero with your register dump, pls double check it and post back you reply.
Hi SathyaKumar ,
Thanks for your advice, I checked all registers and found that the ISP_CTRL.SHIFT should be set to shift 4bits, rather than 2bits.
After changing, the camera image became stable without rolling or blurred screen. But it still fills only a quarter of the top screen.
the image was as follows:
To check format selection of YUV422 could be showed correctly, I wrote a function to fill the image data buffer with a special graph according to YUV422 data format, so it should show as follows:
However , it actual showed as follows:
to "ISP_CTRL.IRQ0ENABLE is zero with your register dump", it because the register dump is printed before enable the interrupt.
After enable the camera interrupt, the registers value are as follows:
ISP_SYSCONFIG =0x1001 ISP_CTRL =0x9c18cTCTRL_CTRL =0x9ISP_IRQ0ENABLE =0x80000100CCDC_SYN_MODE =0x31004CCDC_PCR =0x1CCDC_HORZ_INFO =0x27fCCDC_VERT_START =0x0CCDC_VERT_LINES =0x1dfCCDC_CFG =0x8800CCDC_HORZ_INFO =0x27fCCDC_VERT_START =0x0CCDC_HSIZE_OFF =0x500OALIntrTranslateIrq(Irq 24 to sysIntr 31)
CCDC_SDOFST =0x0CCDC_SDR_ADDR =0x86a1e000CCDC_VDINT =0x1df01dfCCDC_ALAW =0x4CCDC_FMTCFG =0x4000CCDC_FMT_HORZ =0x0CCDC_FMT_VERT =0x0CCDC_VP_OUT =0x0
the YUV422 filling function:
DWORD CCameraPdd::YUVBufferFill( ULONG ulModeType, PUCHAR pImage ){ PCS_VIDEOINFOHEADER pCsVideoInfoHdr = &m_pCurrentFormat[ulModeType].VideoInfoHeader;
UINT biWidth = pCsVideoInfoHdr->bmiHeader.biWidth; UINT biHeight = abs(pCsVideoInfoHdr->bmiHeader.biHeight); UINT biSizeImage = pCsVideoInfoHdr->bmiHeader.biSizeImage; DWORD biCompression = pCsVideoInfoHdr->bmiHeader.biCompression; biCompression &= ~BI_SRCPREROTATE;
if ( ( FOURCC_YUY2 != biCompression ) && ( FOURCC_YV12 != biCompression ) ) { return -1; }
// make the box width/height 1/8th of the screen, so it's visible but doesn't // overwhelm UINT uiBoxWidth = biWidth/BOXWIDTHDIVIDER; UINT uiBoxHeight = biHeight/BOXHEIGHTDIVIDER;
float fWidthStep = (float) (biWidth - uiBoxWidth)/LOCATIONWIDTHMASK; float fHeightStep = (float) (biHeight - uiBoxHeight)/LOCATIONHEIGHTMASK;
UINT x, y; UINT uiTickCount; UINT uiDirection; UINT uiLocationX, uiLocationY;
uiTickCount = GetTickCount() >> SPEEDSHIFT;
// and the result with 0x3 so the value ranges between 0 and 3 for the direction. uiDirection = (uiTickCount >> LOCATIONSHIFT) & 0x3;
uiLocationX = static_cast<UINT>(fWidthStep * (uiTickCount & LOCATIONWIDTHMASK)); uiLocationY = static_cast<UINT>(fHeightStep * (uiTickCount & LOCATIONHEIGHTMASK));
RETAILMSG(1,(_T(" uiDirection=%d,\r\n "),uiDirection)); switch (uiDirection) { case 0: x = uiLocationX; y = 0; break; case 1: x = biWidth - uiBoxWidth; y = uiLocationY; break; case 2: x = (biWidth - uiBoxWidth) - uiLocationX; y = biHeight - uiBoxHeight; break; case 3: x = 0; y = (biHeight - uiBoxHeight) - uiLocationY; break; } RETAILMSG(1,(_T(" x=%d,y=%d,\r\n "),x,y)); if (MAKEFOURCC('Y','V','1','2') == biCompression ) { UINT uiStride = (2 * biSizeImage) / (3 * biHeight); UINT uiDelta = uiStride-biWidth; UINT uiSizeYPlane = uiStride * biHeight; UINT uiHalfStride = uiStride >> 1; UINT uiHalfWidth = biWidth >> 1; UINT uiHalfDelta = uiHalfStride - uiHalfWidth;
// 1. Make the entire image white.
// Y plane for (UINT i = 0; i < uiSizeYPlane; i += uiStride) { memset(&pImage[i], Y_WHITE, biWidth); memset(&pImage[i+biWidth], 0, uiDelta); }
// V & U planes for (; i < biSizeImage; i += uiHalfStride) { memset(&pImage[i], VU_BOTH, uiHalfWidth); memset(&pImage[i+uiHalfWidth], 0, uiHalfDelta); }
// 2. Add the black square. Since the chroma (V & U) values are the same // for both black and white, we only have to touch the luma (Y) plane. UINT uiBound = ((y + uiBoxHeight) * uiStride) + (x + uiBoxWidth);
for (i = (y * uiStride) + x; i < uiBound; i += uiStride) { memset(&pImage[i], Y_BLACK, uiBoxWidth); } } else if (MAKEFOURCC('Y','U','Y','2') == biCompression ) { UINT uiStrideDWORD = (biSizeImage / biHeight) / sizeof(DWORD); UINT uiWidthDWORD = biWidth / 2; UINT uiDeltaDWORD = uiStrideDWORD - uiWidthDWORD;
DWORD* pdwImage = reinterpret_cast<DWORD*>(pImage); ASSERT(pdwImage); if (!pdwImage) { return 0; } RETAILMSG(1,(_T(" biHeight=%d,\r\n uiWidthDWORD=%d,\r\n uiDeltaDWORD=%d,\r\n"), biHeight,uiWidthDWORD,uiDeltaDWORD));
for (UINT i = 0; i < biHeight; i++) { for (UINT j = 0; j < uiWidthDWORD; j++) *pdwImage++ = MACROPIXEL_RED;
for (j = 0; j < uiDeltaDWORD; j++)
*pdwImage++ = 0; }
}
return(biSizeImage);}