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

📄 camera.cpp

📁 wince 6.0 摄像头(ov7670)驱动,已在ce6测试通过
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//

#include <windows.h>
#include <pm.h>
#include "Cs.h"
#include "Csmedia.h"

#include "CameraPDDProps.h"
#include "dstruct.h"
#include "dbgsettings.h"
#include <Camera.h>
#include "CameraDriver.h"
#include "PinDriver.h"

#include "camerapdd.h"
#include "pdd_private.h"

TCHAR *dev_name = L"CAM1";

void CCameraPdd::init_ipm_client()
{
    //set up IPM
    //TCHAR szTemp[MAX_PATH];
    IPM_STATUS_T status;
    is_ipm_enabled = FALSE;
    ipm_block_ref_count = 0;
    // IPM Registration:
    status = IPM_Register(dev_name, &(ipm_client_id) ,3000);
    if ( status==IPM_STATUS_SUCCESS)
    {
        DWORD dwProcState;        
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Registration Completed, client id is %d\r\n",dev_name, ipm_client_id));
        dwProcState = IPM_PROCESSOR_D0_RDY | IPM_PROCESSOR_RING_OSC_RDY  | IPM_PROCESSOR_D2_RDY| IPM_PROCESSOR_D1_RDY; // Initial

        // Notify IPM         
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Initial Notify IPM Ready For Processor state. dwProcState=%x \r\n", dev_name, dwProcState));
        if (IPM_NotifyReadyForProcState(ipm_client_id, dwProcState ,3000) != IPM_STATUS_SUCCESS)        
            DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Notify IPM Ready For Processor state for driver FAILED\r\n", dev_name));
        is_ipm_enabled = TRUE;
    }
    else if(status == IPM_STATUS_IPM_DISABLED)        
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] NOIPM \r\n", dev_name));
    else        
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Registration Failed, IPM Error %d\r\n", dev_name, status));
}

void CCameraPdd::set_ipm_block(BOOL is_on)
{
    if (!is_ipm_enabled)
        return;

    if (is_on)
    {
        ipm_block_ref_count++;
        if (ipm_block_ref_count > 1)
            return;
    }
    else
    {
        if (ipm_block_ref_count)
        {
            ipm_block_ref_count--;
            if (ipm_block_ref_count)
                return;
        } else
            return;
    }
    
    DEBUGMSG(ZONE_IOCTL,(L"CAM: set_ipm_block %d, ref count %d!\r\n", is_on, ipm_block_ref_count));
    
    DWORD dwProcState;
    dwProcState = IPM_PROCESSOR_D0_RDY
                | IPM_PROCESSOR_RING_OSC_RDY  
                | IPM_PROCESSOR_D2_RDY
                | IPM_PROCESSOR_D1_RDY; // Initial

    if (ipm_block_ref_count)
        dwProcState = IPM_PROCESSOR_D0_RDY;

    IPM_STATUS_T status;
    status = IPM_NotifyReadyForProcState(ipm_client_id, dwProcState, 1000);
        
    if (status != IPM_STATUS_SUCCESS)        
        DEBUGMSG( ZONE_IOCTL, ( _T("CAM: camera IPM_NotifyReadyForProcState failed!\r\n")) );
    if (ipm_block_ref_count)
        status = IPM_SetFreqChangeBlock(ipm_client_id, 1000);
    else
        status = IPM_ReleaseFreqChangeBlock(ipm_client_id, 1000);

    if (status != IPM_STATUS_SUCCESS)
        DEBUGMSG( ZONE_IOCTL, ( _T("CAM: camera IPM_SetFreqChangeBlock failed!\r\n")) );
        
}

void CCameraPdd::power_on()
{
    qci_clock_enable(1);
    qci_set_interface(sensor->get_qci_interface());
    sensor->set_power_mode(1);
    Sleep(1);
}

bool CCameraPdd::detect_sensor()
{
    set_ipm_block(1);
    power_on();

    qci_enable();
    Sleep(150);
    bool detected = sensor->detect();
    if (detected)
        sensor->stop_capture();
    is_sensor_on = 1;

    set_ipm_block(0);
    return detected;
}

void CCameraPdd::power_off()
{
    qci_stop_capture();
    sensor->set_power_mode(0);
    qci_clock_enable(0);
    is_sensor_on = 0;
}
 
void CCameraPdd::set_capture_format(int sensor_format,
                                    FrameSize sensor_size,
                                    format_t* qci_format)
{
    qci_master_timing_t timing;

    timing.width = qci_format->width - 1;
    timing.height = qci_format->height - 1;
    if (qci_format->format != sensor_format)
        timing.height++;
    timing.timing = sensor->get_timing();
    sensor->set_frame_format(sensor_format, sensor_size);
    qci_set_master_timing(&timing);
    qci_set_image_format(sensor_format, qci_format->format);
    qci_set_frame_format(qci_format);
}

void CCameraPdd::start_capture(ULONG mode)
{
    
    set_ipm_block(1);
    PCS_VIDEOINFOHEADER video_info;

    video_info = &m_pCurrentFormat[mode].VideoInfoHeader;
    UINT32 width        = video_info->bmiHeader.biWidth;
    UINT32 height       = video_info->bmiHeader.biHeight;

    qci_image_proc_cfg_t qci_cfg;
    qci_image_proc_cfg_t* qci_cfg_ptr = 0;

    float *coe;

    if (!is_sensor_on)
        detect_sensor();

    camera_cfg = sensor->get_camera_cfg(video_info, mode);

    set_capture_format(camera_cfg->sensor_format,
                       camera_cfg->sensor_size,
                       &camera_cfg->qci_format);

    // coefficent for color conversion. 
    if (camera_cfg->color_cfg)
    {
        coe = camera_cfg->color_cfg->color_correct_coe;
        qci_cfg.coe.k00 = QCI_COE_CONVERT(0.299 * coe[0] + 0.587 * coe[3] + 0.114 * coe[6]);
        qci_cfg.coe.k01 = QCI_COE_CONVERT(0.299 * coe[1] + 0.587 * coe[4] + 0.114 * coe[7]);
        qci_cfg.coe.k02 = QCI_COE_CONVERT(0.299 * coe[2] + 0.587 * coe[5] + 0.114 * coe[8]);

        qci_cfg.coe.k10 = QCI_COE_CONVERT(-0.16874 * coe[0] -0.33126 * coe[3] + 0.5 * coe[6]);
        qci_cfg.coe.k11 = QCI_COE_CONVERT(-0.16874 * coe[1] -0.33126 * coe[4] + 0.5 * coe[7]);
        qci_cfg.coe.k12 = QCI_COE_CONVERT(-0.16874 * coe[2] -0.33126 * coe[5] + 0.5 * coe[8]);

        qci_cfg.coe.k20 = QCI_COE_CONVERT(0.5 * coe[0] -0.41869 * coe[3] - 0.08131 * coe[6]);
        qci_cfg.coe.k21 = QCI_COE_CONVERT(0.5 * coe[1] -0.41869 * coe[4] - 0.08131 * coe[7]);
        qci_cfg.coe.k22 = QCI_COE_CONVERT(0.5 * coe[2] -0.41869 * coe[5] - 0.08131 * coe[8]);

        qci_cfg.scale = 0;
        qci_cfg.black_level = camera_cfg->color_cfg->black_level;
        qci_cfg.lut = camera_cfg->color_cfg->gama;
        qci_cfg_ptr = &qci_cfg;
    }

    // CMU will not be enabled when input is raw data
    if (camera_cfg->qci_format.format != PXA_CAMERA_IMAGE_FORMAT_RAW10)
        qci_set_image_proc_cfg(qci_cfg_ptr);

#define DEFAULT_STILL_SKIPS 2
    qci_start_capture(mode == STILL? DEFAULT_STILL_SKIPS : 0);
    sensor->start_capture();
}

void CCameraPdd::stop_capture()
{
    sensor->stop_capture();
    qci_stop_capture();
    set_ipm_block(0);
}

const UINT32 color_proc_max_width = 1280;
const UINT32 color_proc_max_height = 1024;

void fill_plane(PUCHAR dest, plane_t* plane, UINT32 size)
{
    DEBUGMSG(ZONE_IOCTL,(L"CAM: DestAddr:0x%08x, BufAddr:0x%08x, size:%d\r\n", dest, plane->buf.buf, size));
    memcpy(dest, plane->buf.buf, plane->buf.size);
}

void fill_plane_cb_cr(PUCHAR dest, PUCHAR src, 
                      UINT32 width, UINT32 height)
{
    
    for (UINT32 i = 0; i < height; i++)
    {
        memcpy(dest, src, width);
        dest += width;
        src += width << 1;
    }
}

void fill_buffer_yv12(PUCHAR* dest_plane, frame_t* frame)
{
    format_t *format = &frame->list->format;
    UINT32 y_size = format->width * format->height;
    
    fill_plane(dest_plane[0], &frame->plane[0], y_size);
    
    DEBUGMSG(ZONE_IOCTL,(L"CAM: DestAddr:0x%08x, BufAddr:0x%08x, cbcr...", dest_plane[2], frame->plane[1].buf.buf));    
    fill_plane_cb_cr(dest_plane[2], (PUCHAR)frame->plane[1].buf.buf, 
        format->width >> 1, format->height >> 1);
    
    DEBUGMSG(ZONE_IOCTL,(L"CAM: DestAddr:0x%08x, BufAddr:0x%08x, cbcr...", dest_plane[1], frame->plane[2].buf.buf));    
    fill_plane_cb_cr(dest_plane[1], (PUCHAR)frame->plane[2].buf.buf, 
        format->width >> 1, format->height >> 1);
}

#define CROP_RGGB
void convert_rggb10_rgb565(UINT16 *dst, UINT16 *src, 
              UINT32 dst_width, UINT32 dst_height,
              UINT32 src_width, UINT32 src_height)
{
    UINT32 src_x0_pos = 0;
    UINT32 src_pos = 0;

    UINT32 line_step = src_height / dst_height / 2;
    line_step *= 2;
    UINT32 col_step = src_width / dst_width / 2;
    col_step *= 2;
    UINT32 src_size = src_width * src_height;

#ifdef CROP_RGGB
    line_step = 2;
    col_step = 2;
#endif

    UINT32 line, col;

    for (line = 0; line < dst_height && (src_x0_pos + src_width) < src_size; line++)
    {
        for (col = 0; col < dst_width && (src_pos + 1 - src_x0_pos) < src_width; col++)
        {
            UINT16 r = src[src_pos];
            UINT16 g = (src[src_pos + 1] + src[src_pos + src_width]) >> 1;
            UINT16 b = src[src_pos + src_width + 1];

            dst[line * dst_width + col] = ((r >> 5) << 11) | ((g >> 4) << 5) | (b >> 5);
            src_pos += col_step;
        }
        src_x0_pos += src_width * line_step;
        src_pos = src_x0_pos;
    }
}


#ifndef _CALLBACK
#define _CALLBACK __STDCALL
#endif

void* _CALLBACK ippiMalloc(int size)
{
    return malloc(size);
}

void _CALLBACK ippiFree(void* pSrcBuf)
{
    free(pSrcBuf);
}

⌨️ 快捷键说明

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