📄 ov2630.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 <ceddk.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 "SensorFormats.h"
#include "monahans.h"
#include "Ov2630.h"
#include "Ov2630_hw.h"
#include "Camera_SOC.h"
//#include "ost.h"
#include "GPIO_platform.h"
#include "GPIO_SOC.h"
#include "GPX_API.h"
PHYSICAL_ADDRESS PA;
MAKE_STREAM_MODE_YV12(DCAM_StreamMode_CIF_YV12, 352, -288, 12, 15);
MAKE_STREAM_MODE_YV12(DCAM_StreamMode_SVGA_YV12, 800, -600, 12, 30);
MAKE_STREAM_MODE_YV12(DCAM_StreamMode_UXGA_YV12, 1600, -1200, 12, 15);
UCHAR get_analog_gain(UINT16 gain);
void get_digi_gain(UINT16 gain, UCHAR* digi_gain1, UCHAR* digi_gain2);
static color_cfg_t color_cfg =
{
0,
(UCHAR*)NULL,
{
(float)1.036, (float)0.097, (float)-0.133,
(float)-0.006, (float)1.217, (float)-0.211,
(float)0.012, (float)-0.386, (float)1.374
}
};
static camera_cfg_t preview_cfg =
{
&DCAM_StreamMode_CIF_YV12,
PXA_CAMERA_IMAGE_FORMAT_RAW10, /* sensor format */
CIF,
/* qci_format_t */
{
PXA_CAMERA_IMAGE_FORMAT_RAW10,
352, 288
},
&color_cfg
};
static camera_cfg_t still_svga_cfg =
{
&DCAM_StreamMode_SVGA_YV12,
PXA_CAMERA_IMAGE_FORMAT_RAW10, /* sensor format */
SVGA,
/* qci_format_t */
{
PXA_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR,
800, 600
},
&color_cfg
};
static camera_cfg_t still_cfg =
{
&DCAM_StreamMode_UXGA_YV12,
PXA_CAMERA_IMAGE_FORMAT_RAW10, /* sensor format */
UXGA,
/* qci_format_t */
{
PXA_CAMERA_IMAGE_FORMAT_RAW10,
1600, 1200
},
&color_cfg
};
static qci_interface_t ov2630_interface =
{
PXA_CI_MODE_MP,
PXA_CI_DATA_WIDTH10,
2600,
FALSE,
FALSE,
FALSE
};
static UCHAR lut[] = {
// RED LUT
0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c,
0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,
0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c,
0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,
0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,
// BLUE LUT
0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c,
0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,
0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c,
0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,
0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,
// GREEN LUT
0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c,
0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,
0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c,
0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,
0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,
};
#define SENSOR_INIT_WAIT 150
#ifdef DEBUG
static void dump_Ov2630();
#endif
static IppiRawPixProcSpec_P3R* rggb2yuv_init(UINT32 width,
UINT32 height,
float* coe);
static BOOL rggb2yuv_convert(PUCHAR* dest, frame_t* frame, IppiRawPixProcSpec_P3R *ippiRPPSpec);
static void rggb2yuv_deinit(IppiRawPixProcSpec_P3R *ippiRPPSpec);
extern void fill_buffer_yv12(PUCHAR* dest_plane, frame_t* frame);
Ov2630::Ov2630()
{
//map_registers();
qci_interface = &ov2630_interface;
timing.BFW = 0x01;
timing.BLW = 0x01; /*GRBG to RGGB*/
rpp_uxga = rggb2yuv_init(1600, 1200, color_cfg.color_correct_coe);
rpp_cif = rggb2yuv_init(352, 288, color_cfg.color_correct_coe);
}
bool Ov2630::detect()
{
UINT8 pid = 0, rev = 0;
OV2630VersionRevision(&pid, &rev);
DEBUGMSG(ZONE_IOCTL,(L"CAM: 2630 sensor PID %d, REV %d\r\n",pid, rev));
return pid == PIDH_OV2630 && rev == PIDL_OV2630;
}
UINT32 Ov2630::get_formats(ULONG type, PCS_DATARANGE_VIDEO** formats)
{
// Video Format initialization
UINT32 nformats = 1;
*formats = new PCS_DATARANGE_VIDEO[nformats];
if( NULL == *formats )
{
return 0;
}
switch (type)
{
case CAPTURE:
case PREVIEW:
(*formats)[0] = &DCAM_StreamMode_CIF_YV12;
break;
case STILL:
(*formats)[0] = &DCAM_StreamMode_UXGA_YV12;
break;
default:
break;
}
return nformats;
}
void Ov2630::start_capture()
{
UINT16 exposure = 250;
UINT16 gain = 4;
if (frame_size == UXGA)
{
exposure *= 2;
}
OV2630AutoFunctionOff();
OV2630ViewfinderOn();
set_exposure_gain(exposure, gain);
// dump_Ov2630();
}
void Ov2630::stop_capture()
{
OV2630ViewfinderOff();
}
extern void set_voltage(UCHAR camera_ana, UCHAR camera_io, UCHAR camera_core, BOOL is_on);
void Ov2630::set_power_mode(bool is_on)
{
set_voltage(0xa, 0xa, 0x0, is_on);
//(P_XLLP_GPIO_T)gpio_reg;
/* Call_GPX */
GPX_SetDirection(GPX_GPIO_CAMERA_HI_PWDN, PXA_GPIO_DIRECTION_OUT);
OV2630PowerDown(is_on? PXA_CAMERA_POWER_FULL : PXA_CAMERA_POWER_OFF);
if (is_on)
Sleep(200);
}
camera_cfg_t* Ov2630::get_camera_cfg(PCS_VIDEOINFOHEADER pCsVideoInfoHdr, ULONG mode)
{
UINT32 width = abs(pCsVideoInfoHdr->bmiHeader.biWidth);
UINT32 height = abs(pCsVideoInfoHdr->bmiHeader.biHeight);
if (width == 352 && height == 288)
return &preview_cfg;
else if (width == 1600 && height == 1200)
return &still_cfg;
else if (width == 800 && height == 600)
return &still_svga_cfg;
return 0;
}
void Ov2630::set_frame_format(int format, FrameSize size)
{
OV2630Reset();
frame_size = size;
//PXA_CI_MP_TIMING timing;
//int status;
//XLLP_UINT32_T ovSizeFormat, ovFormat;
UINT32 width, height;
UINT32 x[2], y[2];
switch(size)
{
case CIF:
width = 352;
height = 288;
break;
case UXGA:
default:
width = 1600;
height = 1200;
break;
}
OV2630SetFormat(width, height, &x[0], &y[0], &x[1], &y[1]);
}
void Ov2630::handle_frame_interrupt(PUCHAR buf,
CS_BITMAPINFOHEADER* info_header,
frame_t* frame)
{
UINT32 width = abs(info_header->biWidth);
UINT32 height = abs(info_header->biHeight);
UINT32 y_size = width * height;
format_t* format = &frame->list->format;
if (width != format->width && height != format->height)
{
DEBUGMSG(ZONE_IOCTL,(L"CAM: unexpected frame size!!!\r\n"));
return;
}
PUCHAR dest[3];
dest[0] = buf;
dest[2] = dest[0] + y_size;
dest[1] = dest[2] + (y_size >> 2);
switch (format->format)
{
case PXA_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR:
fill_buffer_yv12(dest, frame);
break;
case PXA_CAMERA_IMAGE_FORMAT_RAW10:
DEBUGMSG(ZONE_IOCTL,(L"CAM: converting raw data!!!\r\n"));
handle_frame_raw10(buf, frame);
break;
default:
DEBUGMSG(ZONE_IOCTL,(L"CAM: unsupported frame format %d!!!\r\n"));
}
return;
}
void Ov2630::handle_frame_raw10(PUCHAR buf, frame_t* frame)
{
format_t* format = &frame->list->format;
IppiRawPixProcSpec_P3R* raw_spec;
UINT32 y_size = format->width * format->height;
PUCHAR dest[3];
dest[0] = buf;
dest[2] = dest[0] + y_size;
dest[1] = dest[2] + (y_size >> 2);
DEBUGMSG( ZONE_IOCTL, ( _T("CAM: Ov2630::handle_frame_raw10 dest plane 0x%08x, 0x%08x, 0x%08x\r\n"), dest[0], dest[1], dest[2]) );
raw_spec = format->width == 352? rpp_cif : rpp_uxga;
rggb2yuv_convert(dest, frame, raw_spec);
}
#ifdef DEBUG
static void dump_Ov2630()
{
UCHAR buf[0x8b];
OV2630ReadAllRegs(buf, 0x8b);
for (int i = 0; i < 0x8b; i++)
DEBUGMSG(ZONE_IOCTL,(L"reg %x = %x", i, buf[i]));
}
#endif
#define IPP_COE_FLOAT_TO_INT(x) ((short)((x) * (1 << 8) + 0.5))
static Ipp16s pMatrix[9];
static IppiRawPixProcCfg_P3R ippiRPPCfg;
static IppiCAMCfg ippiCAMCfg;
static IppiRawPixProcSpec_P3R *rggb2yuv_init(UINT32 width,
UINT32 height,
float* coe)
{
IppiRawPixProcSpec_P3R *ippiRPPSpec = NULL;
for (int i = 0; i < sizeof(pMatrix) / sizeof(pMatrix[0]); i++)
{
pMatrix[i] = IPP_COE_FLOAT_TO_INT(coe[i]);
DEBUGMSG(ZONE_IOCTL,(L"matrix[%d] %d", i, pMatrix[i]));
}
/* Initializae CAMCfg structure */
ippiCAMCfg.DPMLen = 0;
ippiCAMCfg.DPMOffset.x = 0;
ippiCAMCfg.DPMOffset.y = 0;
ippiCAMCfg.DPInterp = ippCameraInterpNearest;
ippiCAMCfg.GammaFlag = ippGamPreOneTable;
ippiCAMCfg.GammaIndex[0] = 0;
ippiCAMCfg.pCCMatrix = pMatrix;
ippiCAMCfg.pDeadPixMap = NULL; /* if no dead pixel map */
ippiCAMCfg.pGammaTable[0] = NULL;
ippiCAMCfg.pGammaTable[1] = NULL;
ippiCAMCfg.pGammaTable[2] = NULL;
/* Initialize RPPCfg structure */
ippiRPPCfg.interpolation = ippCameraInterpBilinear;
ippiRPPCfg.colorConversion = ippCameraCscRGGBToYCbCr420;
ippiRPPCfg.rotation = ippCameraRotate180;;
ippiRPPCfg.srcSize.width = width;
ippiRPPCfg.srcSize.height = height;
ippiRPPCfg.srcStep = width << 1;
ippiRPPCfg.dstSize.width = width;
ippiRPPCfg.dstSize.height = height;
ippiRPPCfg.dstStep[0] = ippiRPPCfg.dstSize.width;
ippiRPPCfg.dstStep[1] = ippiRPPCfg.dstSize.width >> 1;
ippiRPPCfg.dstStep[2] = ippiRPPCfg.dstSize.width >> 1;
ippiRPPCfg.bExtendBorder = ippFalse;
/* call init function */
if (ippiInitAlloc_10RGGBtoYCbCr_RotRsz_P3R(&ippiCAMCfg, &ippiRPPCfg, &ippiRPPSpec) != ippStsOk)
{
DEBUGMSG(ZONE_IOCTL,(L"CAM: init ipp failed!!!"));
return 0;
};
return ippiRPPSpec;
}
static BOOL rggb2yuv_convert(PUCHAR* dest, frame_t* frame, IppiRawPixProcSpec_P3R *ippiRPPSpec)
{
format_t* format = &frame->list->format;
Ipp8u *pSrc;
//Ipp8u *pDst[3];
int rv;
pSrc = (Ipp8u*)frame->plane[0].buf.buf;
DEBUGMSG(ZONE_IOCTL,(L"CAM: conver 0x%08x pSrc 0x%08x format 0x%08x\r\n", frame, pSrc, format));
rv = ippi10RGGBtoYCbCr_RotRsz_8u_P3R(pSrc, dest, ippiRPPSpec);
if (rv != ippStsOk)
return FALSE;
return TRUE;
}
static void rggb2yuv_deinit(IppiRawPixProcSpec_P3R *ippiRPPSpec)
{
if (ippiRPPSpec)
ippiFree_10RGGBtoYCbCr_RotRsz_P3R(ippiRPPSpec);
}
void Ov2630::write_sensor_reg(UCHAR addr, UCHAR data)
{
OV2630WriteSensorReg(addr, &data);
}
void Ov2630::set_exposure_gain(UINT16 time, UINT16 gain)
{
DEBUGMSG(ZONE_IOCTL,(L"CAM: Ov2630 exposure %d\n", time));
UCHAR digi_gain1, digi_gain2;
get_digi_gain(gain, &digi_gain1, &digi_gain2);
UCHAR reg_aech = (UCHAR)((time & 0xfc00) >> 10);
reg_aech |= digi_gain1 << 6;
write_sensor_reg(0x8a, 0);
write_sensor_reg(0x45, reg_aech);
write_sensor_reg(0x4c, digi_gain2 << 5);
write_sensor_reg(0x10, (UCHAR)((time & 0x3fc) >> 2));
write_sensor_reg(0x04, (UCHAR)(time & 0x3));
write_sensor_reg(0x0, get_analog_gain(gain));
}
UCHAR get_analog_gain(UINT16 gain)
{
UINT32 i = 0;
if (gain > 32)
gain = 32;
UCHAR sensor_gain = 0;
DEBUGMSG(ZONE_IOCTL,(L"CAM: Ov2630 gain %d\n", gain));
while(gain > 2 && i < 4)
{
gain = gain / 2;
sensor_gain |= 0x10 << i;
i++;
}
UCHAR small_gain = (UCHAR)(gain * 16) - 16;
if (small_gain >= 16)
small_gain = 15;
sensor_gain |= small_gain;
return sensor_gain;
}
UCHAR digi_gain_convert(UCHAR gain)
{
if (gain <= 1)
return 0;
if (gain <= 3)
return 1;
else
return 3;
}
void get_digi_gain(UINT16 gain, UCHAR* digi_gain1, UCHAR* digi_gain2)
{
UCHAR gain1 = 1, gain2 = 1;
if (gain <= 32)
{
digi_gain1 = digi_gain2 = 0;
return;
}
gain = gain / 32;
if (gain > 4)
{
gain2 = gain / 4;
gain1 = 4;
} else
gain1 = (UCHAR)gain;
*digi_gain1 = digi_gain_convert(gain1);
*digi_gain2 = digi_gain_convert(gain2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -