This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAP3530+OV3640 driver for wince6.0

Other Parts Discussed in Thread: OMAP3530, SYSCONFIG

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
    -CCDCInit
    ISP_SYSCONFIG =0x1001
    ISP_CTRL =0x98140
    TCTRL_CTRL =0x9
    ISP_IRQ0ENABLE =0x0
    CCDC_SYN_MODE =0x32700
    CCDC_PCR =0x0
    CCDC_HORZ_INFO =0x27f
    CCDC_VERT_START =0x0
    CCDC_VERT_LINES =0x1df
    CCDC_CFG =0x8000
    CCDC_HORZ_INFO =0x27f
    CCDC_VERT_START =0x0
    CCDC_HSIZE_OFF =0x500
    CCDC_SDOFST =0x0
    CCDC_SDR_ADDR =0x869ee000
    CCDC_VDINT =0x1df0000
    CCDC_ALAW =0x4
    CCDC_FMTCFG =0x4000
    CCDC_FMT_HORZ =0x0
    CCDC_FMT_VERT =0x0
    CCDC_VP_OUT =0x0
    RSZ_PCR =0x4
    RSZ_CNT =0x3fcff
    RSZ_OUT_SIZE =0x0
    RSZ_IN_START =0x0
    RSZ_IN_SIZE =0x0
    RSZ_SDR_OUTADD =0x0
    RSZ_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.SHIFT should be selected based on data lines used.
    • ISP_CTRL.PAR_BRIDGE bit can be selected as per your interface connection.
    • Try disabling ALAW compression.
    • Check whether format selection register in sensor side is set to YUV422 and no compression is enabled. 

    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 =0x9c18c
    TCTRL_CTRL =0x9
    ISP_IRQ0ENABLE =0x80000100
    CCDC_SYN_MODE =0x31004
    CCDC_PCR =0x1
    CCDC_HORZ_INFO =0x27f
    CCDC_VERT_START =0x0
    CCDC_VERT_LINES =0x1df
    CCDC_CFG =0x8800
    CCDC_HORZ_INFO =0x27f
    CCDC_VERT_START =0x0
    CCDC_HSIZE_OFF =0x500
    OALIntrTranslateIrq(Irq 24 to sysIntr 31)

    CCDC_SDOFST =0x0
    CCDC_SDR_ADDR =0x86a1e000
    CCDC_VDINT =0x1df01df
    CCDC_ALAW =0x4
    CCDC_FMTCFG =0x4000
    CCDC_FMT_HORZ =0x0
    CCDC_FMT_VERT =0x0
    CCDC_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);
    }