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

📄 pxa27x_camera.c

📁 该BSP是基于PXA270+WINCE的BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
{
    *bufP = 0;

    if(g_HwContext.XllpCAMERA.camera_functions->ReadRegister)
    {
        XllpLock(I2C);
        g_HwContext.XllpCAMERA.camera_functions->ReadRegister(&g_HwContext.XllpCAMERA, subAddress, bufP);
        XllpUnlock(I2C);
    }
    //RETAILMSG(1,(TEXT("Reading register %x with %x\r\n"), subAddress, *bufP));
}

// Start the video capture process initiated by the application
void CameraStartVideoCapture()
{
    XLLP_STATUS_T status;

    EnterCriticalSection(&CameraMutex);

    bDoStillCapture = FALSE;

    XllpLock(I2C);

    // Configure the capture format.  Set the width, height, mode, and the physical addresses of the 
    // start of the descriptor chain.
    g_HwContext.XllpCAMERA.capture_width = g_HwContext.XllpCAMERA.Video_capture_width;
    g_HwContext.XllpCAMERA.capture_height = g_HwContext.XllpCAMERA.Video_capture_height;
    g_HwContext.XllpCAMERA.capture_mode = XLLP_CAMERA_MODE_RECORD;

    g_HwContext.XllpDMA.fifo0_descriptors_physical = VideoCaptureDescriptorPhysicalStartAddress_CH0;
    g_HwContext.XllpDMA.fifo1_descriptors_physical = VideoCaptureDescriptorPhysicalStartAddress_CH1;
    g_HwContext.XllpDMA.fifo2_descriptors_physical = VideoCaptureDescriptorPhysicalStartAddress_CH2;

    // set capture format
    status = PrvCameraSetCaptureFormat(&g_HwContext);
    if (status)
    {
        RETAILMSG(1,(TEXT("Camera init failure inside CameraSetCaptureFormat().\r\n")));
    }

    XllpCameraSetInterruptMask(&g_HwContext.XllpCAMERA, 
                               XLLP_CI_CICR0_FOM            | 
                               XLLP_CI_CICR0_EOFM           | 
                               XLLP_CI_CICR0_SOFM           | 
                               XLLP_CI_CICR0_CDM            |
                               XLLP_CI_CICR0_QDM            |
                               XLLP_CI_CICR0_PERRM          |
                               XLLP_CI_CICR0_EOLM           | 
                               XLLP_CI_CICR0_FEM);

    PrvStartCapture(&g_HwContext, 0, 0);
    
    XllpUnlock(I2C);

    LeaveCriticalSection(&CameraMutex);
}

void CameraStopVideoCapture()
{
    EnterCriticalSection(&CameraMutex);

    XllpLock(I2C);

    // stop capture
    g_HwContext.XllpCAMERA.camera_functions->stop_capture(&g_HwContext.XllpCAMERA);    

    // stop dma
    PrvStopDMATransfer(&g_HwContext);

    XllpUnlock(I2C);

    LeaveCriticalSection(&CameraMutex);
}

void CameraCaptureStillImage()
{
    XLLP_STATUS_T status;

    // stop capture
    g_HwContext.XllpCAMERA.camera_functions->stop_capture(&g_HwContext.XllpCAMERA);    

    // stop dma
    PrvStopDMATransfer(&g_HwContext);

    EnterCriticalSection(&CameraMutex);

    XllpLock(I2C);

    discardframes = 0;

    // Configure the capture format.  Set the width, height, mode, and the physical addresses of the 
    // start of the descriptor chain.
    g_HwContext.XllpCAMERA.capture_width  = g_HwContext.XllpCAMERA.Still_capture_width;
    g_HwContext.XllpCAMERA.capture_height = g_HwContext.XllpCAMERA.Still_capture_height;
    g_HwContext.XllpCAMERA.capture_mode   = XLLP_CAMERA_MODE_STILL;

    g_HwContext.XllpDMA.fifo0_descriptors_physical = StillCaptureDescriptorPhysicalStartAddress_CH0;
    g_HwContext.XllpDMA.fifo1_descriptors_physical = StillCaptureDescriptorPhysicalStartAddress_CH1;
    g_HwContext.XllpDMA.fifo2_descriptors_physical = StillCaptureDescriptorPhysicalStartAddress_CH2;

    // Reset the buffer chain.  The application must now resubmit all capture buffers.
    bFirstVideoCaptureBufferSubmitted = FALSE;
    VirtAddr_Last_Pn_CH0 = 0x0;
    
    // set capture format
    status = PrvCameraSetCaptureFormat(&g_HwContext);
    if (status)
    {
            RETAILMSG(1,(TEXT("Camera init failure inside CameraSetCaptureFormat().\r\n")));
    //      return 1;
    }

    XllpCameraSetInterruptMask(&g_HwContext.XllpCAMERA, 
                               XLLP_CI_CICR0_FOM            | 
                               XLLP_CI_CICR0_EOFM           | 
                               XLLP_CI_CICR0_SOFM           | 
                               XLLP_CI_CICR0_CDM            |
                               XLLP_CI_CICR0_QDM            |
                               XLLP_CI_CICR0_PERRM          |
                               XLLP_CI_CICR0_EOLM           | 
                               XLLP_CI_CICR0_FEM);
    
    bDoStillCapture = TRUE;

    // Enable the still image capture sequence.
    // Calling this routine once results in capture sequence that sometimes fails to interrupt
    // on the end of frame.
    // Calling this routine twice works around this problem - but it needs to be looked into
    // to root cause the failure.
    PrvStartCapture(&g_HwContext, 0, 1);
    PrvStartCapture(&g_HwContext, 0, 1);

    XllpUnlock(I2C);

    LeaveCriticalSection(&CameraMutex);
}

// Shut down this session of the camera driver and free all of the relevent resources allocated within.
int CameraShutdown(void)
{
    DWORD i;
    DESCRIPTOR_INFO_T *pDescriptorInfo;
    
    XllpLock(I2C);

    XllpCameraDeInit(&g_HwContext.XllpCAMERA);

    for (i = 0; i < NumBuffers; i++)
    {
            pDescriptorInfo = MasterBufferList[i];

            free(pDescriptorInfo->pDescriptorBufferPhyAddress);
            free(pDescriptorInfo->pDescriptorBufferVirtAddress);
            free(pDescriptorInfo->pBufferPhyAddress);
            free(pDescriptorInfo);
    }

    free((void *)VirtAddr_Phantom_Buffer_Base_Address);

    NumBuffers = 0;

    // Signal the ISR thread to shutdown
    SetEvent(hShutDown);

    XllpUnlock(I2C);

    return TRUE;
}

// A helper function that is called to configure the parameters that are later used 
// to configure the capture format.
int CameraChangeCaptureFormat(void)
{
    // TBD: call some real function
    return TRUE;
}


// Provides a physical address for a given user mode virtual address.
BOOL getPhyAddress (DWORD * pdwVirtual, DWORD * pdwPhysical)
{
    BOOL bReturnVal = TRUE;
    DWORD dwPageSize = UserKInfo[KINX_PAGESIZE];
    DWORD dwPageTableEntry;
    DWORD dwPageTablePart;
    DWORD dwOffsetInPage;

    /* query the page tables */
    if (LockPages (pdwVirtual, sizeof (DWORD), &dwPageTableEntry, LOCKFLAG_QUERY_ONLY) != TRUE)
    {
            bReturnVal = FALSE;
            goto cleanAndReturn;
    }

    /* shift left to make into a real address */
    dwPageTablePart = dwPageTableEntry << UserKInfo[KINX_PFN_SHIFT];

    /* figure out the offset in the page */
    dwOffsetInPage = ((DWORD) pdwVirtual) & (~UserKInfo[KINX_PFN_MASK]);

    /* combine the page table part and offset to create the address */
    *pdwPhysical = dwPageTablePart | dwOffsetInPage;

    cleanAndReturn:

    return (bReturnVal);
}

//
// Submit a buffer to be filled by the camera DMA.
// A buffer is submitted by chaining the last buffer to this new buffer.
//
// Requires a valid FrameID, which is obtained from a successful call to PrepareBuffer().
//
void CameraSubmitBuffer(P_CAMERA_DMA_BUFFER_INFO pBufInfo, int BufferType)
{
    DESCRIPTOR_INFO_T *pDescriptorInfo;
    XLLP_DMAC_DESCRIPTOR_T *pXPn_CH0;
    XLLP_DMAC_DESCRIPTOR_T *pXPn_CH1;
    XLLP_DMAC_DESCRIPTOR_T *pXPn_CH2;

    XLLP_DMAC_DESCRIPTOR_T *pXn_CH0;
    XLLP_DMAC_DESCRIPTOR_T *pXn_CH1;
    XLLP_DMAC_DESCRIPTOR_T *pXn_CH2;

    XLLP_DMAC_DESCRIPTOR_T *pLast_Pn_CH0;
    XLLP_DMAC_DESCRIPTOR_T *pLast_Pn_CH1;
    XLLP_DMAC_DESCRIPTOR_T *pLast_Pn_CH2;

    XLLP_DMAC_DESCRIPTOR_T *pLast_n_CH0;
    XLLP_DMAC_DESCRIPTOR_T *pLast_n_CH1;
    XLLP_DMAC_DESCRIPTOR_T *pLast_n_CH2;

    BOOL isYUV_PLANAR;

    pDescriptorInfo = NULL;
    if (pBufInfo)
    {
        if (pBufInfo->BufferID < MAX_CAMERA_DMA_BUFFERS)
        {
                pDescriptorInfo = MasterBufferList[pBufInfo->BufferID];
        }
    }
    if (pDescriptorInfo)
    {
        isYUV_PLANAR = (3 == pDescriptorInfo->dwPlanesNumber ? TRUE : FALSE);

        // If this is the first buffer being submitted, then we want to store the physical address of the descriptor chain
        // so that when we start DMA's later on, we start with _this_ buffer.  All buffers submitted after this first buffer
        // are chained behind this one.  Therefore, this buffer is the logical choice to start with.    
        if (BufferType == VIDEO_CAPTURE_BUFFER)
        {
            if (bFirstVideoCaptureBufferSubmitted == FALSE)
            {
                VideoCaptureDescriptorPhysicalStartAddress_CH0 = pDescriptorInfo->pPhysAddr_X1_CH0;
                VideoCaptureDescriptorPhysicalStartAddress_CH1 = pDescriptorInfo->pPhysAddr_X1_CH1;
                VideoCaptureDescriptorPhysicalStartAddress_CH2 = pDescriptorInfo->pPhysAddr_X1_CH2;
                bFirstVideoCaptureBufferSubmitted = TRUE;
            }

            pXPn_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_XPn_CH0;
            pXPn_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_XPn_CH1;
            pXPn_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_XPn_CH2;

            pXn_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_Xn_CH0;
            pXn_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_Xn_CH1;
            pXn_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_Xn_CH2;

            pLast_Pn_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_Pn_CH0;
            pLast_Pn_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_Pn_CH1;
            pLast_Pn_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_Pn_CH2;

            pLast_n_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_n_CH0;
            pLast_n_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_n_CH1;
            pLast_n_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_n_CH2;

            // Chain last phantom descriptor XPn to the first phantom descriptor XP1.
            // This loops the phantom descriptor back to itself.
            pXPn_CH0->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH0;
            if (isYUV_PLANAR) pXPn_CH1->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH1;
            if (isYUV_PLANAR) pXPn_CH2->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH2;

            // Chain the last real descriptor to the start of the phantom descriptor chain
            pXn_CH0->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH0;
            if (isYUV_PLANAR) pXn_CH1->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH1;
            if (isYUV_PLANAR) pXn_CH2->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH2;

            // Chain the last descriptor to this new descriptor by adding this new descriptor to the end of the chain.
            // We either are already looping on the phantom descriptor by the time this frame buffer is submitted, or
            // we have yet to begin looping on the phantom descriptor.  Therefore, we must program the end of the phantom descriptor
            // to branch to the beginning of the new descriptor.  And, if we were not already looping on the phantom descriptor,
            // then we want to program the last real descriptor so that it branches to the beginning of the new descriptor.
            if (VirtAddr_Last_Pn_CH0)
            {
                pLast_Pn_CH0->DDADR = pDescriptorInfo->pPhysAddr_X1_CH0;
                if (isYUV_PLANAR) pLast_Pn_CH1->DDADR = pDescriptorInfo->pPhysAddr_X1_CH1;
                if (isYUV_PLANAR) pLast_Pn_CH2->DDADR = pDescriptorInfo->pPhysAddr_X1_CH2;

                pLast_n_CH0->DDADR = pDescriptorInfo->pPhysAddr_X1_CH0;
                if (isYUV_PLANAR) pLast_n_CH1->DDADR = pDescriptorInfo->pPhysAddr_X1_CH1;
                if (isYUV_PLANAR) pLast_n_CH2->DDADR = pDescriptorInfo->pPhysAddr_X1_CH2;
            }

            // Update pVirtAddr_Last_Pn and pVirtAddr_Last_n so they point to this new buffer

⌨️ 快捷键说明

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