📄 image_sensor.c
字号:
/* SIV100 needs 24M MCLK */
/* Use UPLL to produce 48M clock, then divided by 2 */
DISABLE_CAMERA_TG_CLK_48M;
ENABLE_CAMERA_TG_CLK_48M;
UPLL_Enable(UPLL_OWNER_ISP);
SET_TG_OUTPUT_CLK_DIVIDER(1);
SET_CMOS_RISING_EDGE(0);
SET_CMOS_FALLING_EDGE(1);
/* Sensor Signal Polarity */
/* Note: Set HSync Polarity to Low means High active */
ENABLE_CAMERA_PIXEL_CLKIN_ENABLE;
SET_CMOS_CLOCK_POLARITY_LOW;
SET_VSYNC_POLARITY_LOW;
SET_HSYNC_POLARITY_LOW;
/* YUV Sensor Input Format */
ENABLE_CAMERA_INDATA_FORMAT; /* Enable yuv data input */
SET_CAMERA_INPUT_TYPE(INPUT_YUV422); /* SIV100B support YUV422 */
SET_CAMERA_INPUT_ORDER(INPUT_ORDER_CbYCrY1);
/* Reset the sensor */
RESET_PIN_HIGH;
RESET_PIN_LOW;
for (iI = 0; iI < 500; iI++);
RESET_PIN_HIGH;
for (iI = 0; iI < 500; iI++);
//kal_sleep_task(2); /* delay for stable sensor */
// check sensor's device information
sensor_id1=read_cmos_sensor(0x01);
sensor_id2=read_cmos_sensor(0x02);
kal_prompt_trace(MOD_ENG,"SIV100B_Init---sensor_id1=%d",sensor_id1);
kal_prompt_trace(MOD_ENG,"SIV100B_Init---sensor_id2=%d",sensor_id2);
if ( sensor_id1!= SIV100B_SENSOR_ID || sensor_id2 != SIV100B_SENSOR_VERSION)
{
return -1;
}
SIV100B_Write_Sensor_Initial_Setting();
return 1;
} /* SIV100B_Init() */
/*************************************************************************
* FUNCTION
* ConfigVBlank
*
* DESCRIPTION
* This function is to set VBlank size.
*
* PARAMETERS
* iBlank: target VBlank size
* iHz: banding frequency
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void ConfigVBlank(const kal_uint16 iBlank, const kal_uint8 iHz)
{
/********************************************
* 50Hz-relative registers can not be used *
********************************************/
const kal_uint16 iVal2Write = iBlank - 1;
ASSERT(iBlank < (1 << 10));
switch (iHz) {
case CAM_BANDING_50HZ:
case CAM_BANDING_60HZ:
write_cmos_sensor(0x20, (read_cmos_sensor(0x20) & 0xFC) | ((iVal2Write & 0x0300) >> 8));
write_cmos_sensor(0x22, iVal2Write & 0x00FF);
break;
// case CAM_BANDING_50HZ:
// SIV100B cannot use all blank size registers of 50Hz
// write_cmos_sensor(0x23, (read_cmos_sensor(0x23) & 0xFC) | ((iVal2Write & 0x0300) >> 8));
// write_cmos_sensor(0x25, iVal2Write & 0x00FF);
}
} /* ConfigVBlank */
/*************************************************************************
* FUNCTION
* ConfigHBlank
*
* DESCRIPTION
* This function is to set HBlank size.
*
* PARAMETERS
* iBlank: target HBlank size
* iHz: banding frequency
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void ConfigHBlank(const kal_uint16 iBlank, const kal_uint8 iHz)
{
/********************************************
* 50Hz-relative registers can not be used *
********************************************/
const kal_uint16 iVal2Write = iBlank - 1;
ASSERT(iBlank < (1 << 10));
switch (iHz) {
case CAM_BANDING_50HZ:
case CAM_BANDING_60HZ:
write_cmos_sensor(0x20, (read_cmos_sensor(0x20) & 0xCF) | ((iVal2Write & 0x0300) >> 4));
write_cmos_sensor(0x21, iVal2Write & 0x00FF);
break;
// case CAM_BANDING_50HZ:
// SIV100B cannot use all blank size registers of 50Hz
// write_cmos_sensor(0x23, (read_cmos_sensor(0x23) & 0xCF) | ((iVal2Write & 0x0300) >> 4));
// write_cmos_sensor(0x24, iVal2Write & 0x00FF);
}
} /* ConfigHBlank */
/*************************************************************************
* FUNCTION
* SIV100B_PowerOff
*
* DESCRIPTION
* This function is to turn off sensor module power.
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void SIV100B_PowerOff(void)
{
cis_module_power_on(KAL_FALSE); // power off sensor
SET_SCCB_CLK_LOW;
SET_SCCB_DATA_LOW;
UPLL_Disable(UPLL_OWNER_ISP);
} /* SIV100B_PowerOff */
/*************************************************************************
* FUNCTION
* SIV100B_Get_I2C_ID
*
* DESCRIPTION
* This function return the sensor read/write IDs of I2C I/F.
*
* PARAMETERS
* *pI2C_WriteID : address pointer of sensor's I2C write id
* *pI2C_ReadID : address pointer of sensor's I2C read id
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void SIV100B_Get_I2C_ID(kal_uint8 *pI2C_WriteID, kal_uint8 *pI2C_ReadID)
{
*pI2C_WriteID = SIV100B_I2C_WRITE_ID;
*pI2C_ReadID = SIV100B_I2C_READ_ID;
} /* SIV100B_Get_I2C_ID */
/*************************************************************************
* FUNCTION
* SIV100B_GetSize
*
* DESCRIPTION
* This function return the image width and height of image sensor.
*
* PARAMETERS
* *pWidth : address pointer of horizontal effective pixels of image sensor
* *pHeight : address pointer of vertical effective lines of image sensor
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void SIV100B_GetSize(kal_uint16 *pWidth, kal_uint16 *pHeight)
{
*pWidth = IMAGE_SENSOR_VGA_WIDTH; // valid pixel # in one frame
*pHeight = IMAGE_SENSOR_VGA_HEIGHT; // valid line # in one frame
} /* SIV100B_GetSize */
/*************************************************************************
* FUNCTION
* SIV100B_GetPeriod
*
* DESCRIPTION
* This function return the image width and height of image sensor.
*
* PARAMETERS
* *pPixelNumber : address pointer of pixel numbers in one period of HSYNC
* *pLineNumber : address pointer of line numbers in one period of VSYNC
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void SIV100B_GetPeriod(kal_uint16 *pPixelNumber, kal_uint16 *pLineNumber)
{
/************************************
* No need for YUV sensor driver *
************************************/
// *pPixelNumber = VGA_PERIOD_PIXEL_NUMS; // pixel numbers in one period of HSYNC
// *pLineNumber = VGA_PERIOD_LINE_NUMS; // line numbers in one period of VSYNC
} /* SIV100B_GetPeriod */
/*************************************************************************
* FUNCTION
* SIV100B_Preview
*
* DESCRIPTION
* This function configure the sensor to preview mode.
*
* PARAMETERS
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void SIV100B_Preview(image_sensor_exposure_window_struct *pImage_Window, image_sensor_config_struct *pSensor_Config_Data)
{
kal_uint8 iHV_Mirror = 0;
kal_uint8 iStartX = 0, iStartY = 1;
kal_uint8 iTemp = 0;
volatile kal_uint16 iRetry;
static kal_uint16 iBound = 0x00FF;
write_cmos_sensor(0x40, 0x80); /* enable *NORMAL* AE */
write_cmos_sensor(0x60, 0xC8); /* enable AWB */
if (pSensor_Config_Data->isp_op_mode == ISP_MJPEG_PREVIEW_MODE
|| pSensor_Config_Data->isp_op_mode == ISP_MJPEG_ENCODE_MODE) { // MJPEG mode
g_bVideoMode = KAL_TRUE;
// config TG for video recorder mode
SET_TG_OUTPUT_CLK_DIVIDER(6); // MCLK = 12MHz
SET_CMOS_RISING_EDGE(0);
SET_CMOS_FALLING_EDGE(2);
SET_TG_PIXEL_CLK_DIVIDER(6);
SET_CMOS_DATA_LATCH(2);
}else if (pSensor_Config_Data->frame_rate == 0x0F) { // MPEG4 Encode Mode
g_bVideoMode = KAL_TRUE;
// config TG for video recorder mode
SET_TG_OUTPUT_CLK_DIVIDER(3); // MCLK = 12MHz
SET_CMOS_RISING_EDGE(0);
SET_CMOS_FALLING_EDGE(2);
SET_TG_PIXEL_CLK_DIVIDER(7); /*3*/
SET_CMOS_DATA_LATCH(2);
}else {
g_bVideoMode = KAL_FALSE;
g_bCaptureMode = KAL_FALSE;
iTemp = read_cmos_sensor(0x04) & 0xF3;
write_cmos_sensor(0x04, iTemp | 0x00); // set CLK divider to 1/2
// config TG for camera preview mode
SET_TG_OUTPUT_CLK_DIVIDER(1);
SET_CMOS_RISING_EDGE(0);
SET_CMOS_FALLING_EDGE(1);
SET_TG_PIXEL_CLK_DIVIDER(3); /*1*/
SET_CMOS_DATA_LATCH(1);
}
iHV_Mirror = read_cmos_sensor(0x04) & 0xFC;
switch (pSensor_Config_Data->image_mirror) {
case IMAGE_NORMAL:
iHV_Mirror |= 0x00;
if (g_bVideoMode == KAL_TRUE) {
SET_CAMERA_INPUT_ORDER(INPUT_ORDER_CbYCrY1);
iStartX = 0;
iStartY = 1;
}else {
SET_CAMERA_INPUT_ORDER(INPUT_ORDER_CbYCrY1);
iStartX = 0;
iStartY = 1;
}
break;
case IMAGE_HV_MIRROR:
iHV_Mirror |= 0x03;
if (g_bVideoMode == KAL_TRUE) {
SET_CAMERA_INPUT_ORDER(INPUT_ORDER_CbYCrY1);
iStartX = 0;
iStartY = 1;
}else {
SET_CAMERA_INPUT_ORDER(INPUT_ORDER_CbYCrY1);
iStartX = 0;
iStartY = 1;
}
break;
default:
ASSERT(0);
}
write_cmos_sensor(0x04, iHV_Mirror);
pImage_Window->grab_start_x = iStartX;
pImage_Window->grab_start_y = iStartY;
pImage_Window->exposure_window_width = IMAGE_SENSOR_VGA_WIDTH - iStartX;
pImage_Window->exposure_window_height = IMAGE_SENSOR_VGA_HEIGHT - iStartY;
} /* SIV100B_Preview */
/*************************************************************************
* FUNCTION
* SID201A_Capture
*
* DESCRIPTION
* This function configures the sensor to capture mode.
*
* PARAMETERS
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void SIV100B_Capture(image_sensor_exposure_window_struct *pImage_Window, image_sensor_config_struct *pSensor_Config_Data)
{
kal_uint8 iStartX = 0, iStartY = 1, iTemp;
kal_uint32 iExp;
kal_prompt_trace(MOD_CC,"SIV100B_Capture==1===%s"," start ");
g_bCaptureMode = KAL_TRUE;
if (pSensor_Config_Data->frame_rate == 0xF0) {
/************************************
* Webcam mode, AE/AWB still on *
************************************/
ConfigVBlank(WEBCAM_MODE_VBLANK, CAM_BANDING_50HZ);
ConfigHBlank(WEBCAM_MODE_HBLANK, CAM_BANDING_50HZ);
}else {
/********************************
* Normal camera capture mode *
********************************/
write_cmos_sensor(0x40, 0x00); // disable AE
write_cmos_sensor(0x60, 0x00); // disable AWB
if (pImage_Window->image_target_width <= IMAGE_SENSOR_VGA_WIDTH &&
pImage_Window->image_target_height <= IMAGE_SENSOR_VGA_HEIGHT) {
/********************************************************
* This part captures image size equal to or under VGA *
********************************************************/
if (pImage_Window->digital_zoom_factor >= (ISP_DIGITAL_ZOOM_INTERVAL << 1)) {
iTemp = read_cmos_sensor(0x04) & 0xF3;
write_cmos_sensor(0x04, iTemp | 0x04); // set CLK divider = 1/4
SET_TG_PIXEL_CLK_DIVIDER(3);
SET_CMOS_DATA_LATCH(2);
iExp = (read_cmos_sensor(0x30) << 8) | read_cmos_sensor(0x31);
if (iExp == 1) {
iTemp >>= 1;
write_cmos_sensor(0x30, 0x00);
write_cmos_sensor(0x31, 0x01);
}else {
iExp = (((iExp << 3) + iTemp) >> 1);
write_cmos_sensor(0x30, (iExp >> 11) & 0x00FF);
write_cmos_sensor(0x31, (iExp >> 3) & 0x00FF);
}
}
}
else if (pImage_Window->image_target_width > IMAGE_SENSOR_VGA_WIDTH &&
pImage_Window->image_target_height > IMAGE_SENSOR_VGA_HEIGHT) {
/********************************************
* This part captures image size over VGA *
********************************************/
iTemp = read_cmos_sensor(0x04) & 0xF3;
write_cmos_sensor(0x04, iTemp | 0x0C); // set CLK divider = 1/16
SET_TG_PIXEL_CLK_DIVIDER(15);
SET_CMOS_DATA_LATCH(8);
iExp = (read_cmos_sensor(0x30) << 8) | read_cmos_sensor(0x31);
iExp += 4; // round
write_cmos_sensor(0x03, 0x00); //Brad.Oh 070914
if (pImage_Window->digital_zoom_factor >= (ISP_DIGITAL_ZOOM_INTERVAL << 1)) {
/********************************************************
* Capture SXGA resolution with zoom factor over 2x *
********************************************************/
ConfigHBlank(CP_1M_MODE_ZOOM_HBLANK, CAM_BANDING_50HZ);
if (g_bNightMode == KAL_TRUE) {
if (g_iBanding == CAM_BANDING_50HZ) {
iExp = iExp * (PV_MODE_HVP_PERIOD + PV_MODE_HBLANK_50HZ_NIGHT) / (PV_MODE_HVP_PERIOD + CP_1M_MODE_ZOOM_HBLANK);
}else {
iExp = iExp * (PV_MODE_HVP_PERIOD + PV_MODE_HBLANK_60HZ_NIGHT) / (PV_MODE_HVP_PERIOD + CP_1M_MODE_ZOOM_HBLANK);
}
}else {
if (g_iBanding == CAM_BANDING_50HZ) {
iExp = iExp * (PV_MODE_HVP_PERIOD + PV_MODE_HBLANK_50HZ_NORMAL) / (PV_MODE_HVP_PERIOD + CP_1M_MODE_ZOOM_HBLANK);
}else {
iExp = iExp * (PV_MODE_HVP_PERIOD + PV_MODE_HBLANK_60HZ_NORMAL) / (PV_MODE_HVP_PERIOD + CP_1M_MODE_ZOOM_HBLANK);
}
}
}
if (iExp <= 8) {
//iTemp >>= 1;
write_cmos_sensor(0x30, 0x00);
write_cmos_sensor(0x31, 0x01);
}else {
iExp >>= 3; // iExp / 8
if (iExp < 1) { // make sure nonzero exposure
iExp = 1;
}
write_cmos_sensor(0x30, (iExp >> 8) & 0x00FF);
write_cmos_sensor(0x31, iExp & 0x00FF);
}
kal_sleep_task(1); //Brad.Oh 070914
write_cmos_sensor(0x03, 0xC5); //Brad.Oh 070914
}
}
pImage_Window->grab_start_x = iStartX;
pImage_Window->grab_start_y = iStartY;
pImage_Window->exposure_window_width = IMAGE_SENSOR_VGA_WIDTH - iStartX;
pImage_Window->exposure_window_height = IMAGE_SENSOR_VGA_HEIGHT - iStartY;
kal_prompt_trace(MOD_CC,"SIV100B_Capture==2===%s"," end ");
} /* SIV100B_Capture() */
/*************************************************************************
* FUNCTION
* SIV100B_WriteReg
*
* DESCRIPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -