mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
495 lines
14 KiB
C
495 lines
14 KiB
C
/* Copyright (C) 2024 Alif Semiconductor - All Rights Reserved.
|
|
* Use, distribution and modification of this code is permitted under the
|
|
* terms stated in the Alif Semiconductor Software License Agreement
|
|
*
|
|
* You should have received a copy of the Alif Semiconductor Software
|
|
* License Agreement with this file. If not, please write to:
|
|
* contact@alifsemi.com, or visit: https://alifsemi.com/license
|
|
*
|
|
*/
|
|
|
|
/* System Includes */
|
|
#include "RTE_Device.h"
|
|
#include "RTE_Components.h"
|
|
#include CMSIS_device_header
|
|
#include "Camera_Sensor.h"
|
|
#include "Camera_Sensor_i2c.h"
|
|
#include "Driver_GPIO.h"
|
|
#include "Driver_CPI.h"
|
|
|
|
#if (RTE_OV5647_CAMERA_SENSOR_ENABLE)
|
|
|
|
/* Wrapper function for i2c read
|
|
* read register value from OV5647 Camera Sensor registers
|
|
* using i2c read API \ref camera_sensor_i2c_read
|
|
*
|
|
* for OV5647 Camera Sensor specific i2c configurations
|
|
* see \ref OV5647_camera_sensor_i2c_cnfg
|
|
*/
|
|
#define OV5647_READ_REG(reg_addr, reg_value, reg_size) \
|
|
camera_sensor_i2c_read(&OV5647_camera_sensor_i2c_cnfg, \
|
|
reg_addr, \
|
|
reg_value, \
|
|
(CAMERA_SENSOR_I2C_REG_SIZE)reg_size)
|
|
|
|
/* Wrapper function for i2c write
|
|
* write register value to OV5647 Camera Sensor registers
|
|
* using i2c write API \ref camera_sensor_i2c_write.
|
|
*
|
|
* for OV5647 Camera Sensor specific i2c configurations
|
|
* see \ref OV5647_camera_sensor_i2c_cnfg
|
|
*/
|
|
#define OV5647_WRITE_REG(reg_addr, reg_value, reg_size) \
|
|
camera_sensor_i2c_write(&OV5647_camera_sensor_i2c_cnfg, \
|
|
reg_addr, \
|
|
reg_value, \
|
|
(CAMERA_SENSOR_I2C_REG_SIZE)reg_size)
|
|
|
|
|
|
#define OV5647_CAMERA_SENSOR_SLAVE_ADDR 0x36
|
|
|
|
#define OV5647_CHIP_ID_REGISTER_VALUE 0x5647
|
|
|
|
#define OV5647_SW_STANDBY 0x0100
|
|
#define OV5647_SW_RESET 0x0103
|
|
#define OV5647_REG_CHIPID_H 0x300a
|
|
#define OV5647_REG_CHIPID_L 0x300b
|
|
#define OV5640_REG_PAD_OUT 0x300d
|
|
#define OV5647_REG_FRAME_OFF_NUMBER 0x4202
|
|
#define OV5647_REG_MIPI_CTRL00 0x4800
|
|
#define OV5647_REG_MIPI_CTRL14 0x4814
|
|
|
|
#define MIPI_CTRL00_CLOCK_LANE_GATE BIT(5)
|
|
#define MIPI_CTRL00_LINE_SYNC_ENABLE BIT(4)
|
|
#define MIPI_CTRL00_BUS_IDLE BIT(2)
|
|
#define MIPI_CTRL00_CLOCK_LANE_DISABLE BIT(0)
|
|
|
|
/*Helper macro*/
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
/**
|
|
\brief OV5647 Camera Sensor Register Array Structure
|
|
used for Camera Configuration.
|
|
*/
|
|
typedef struct _OV5647_REG {
|
|
uint16_t reg_addr; /* OV5647 Camera Sensor Register Address*/
|
|
uint16_t reg_value; /* OV5647 Camera Sensor Register Value*/
|
|
} OV5647_REG;
|
|
|
|
/* Wrapper function for Delay
|
|
* Delay for microsecond:
|
|
* Provide busy loop delay
|
|
*/
|
|
#define OV5647_DELAY_uSEC(usec) sys_busy_loop_us(usec)
|
|
|
|
/* OV5647 Camera reset GPIO port */
|
|
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_OV5647_CAMERA_SENSOR_RESET_GPIO_PORT);
|
|
static ARM_DRIVER_GPIO *GPIO_Driver_CAM_RST = &ARM_Driver_GPIO_(RTE_OV5647_CAMERA_SENSOR_RESET_GPIO_PORT);
|
|
|
|
/* I2C Driver Instance */
|
|
extern ARM_DRIVER_I2C ARM_Driver_I2C_(RTE_OV5647_CAMERA_SENSOR_I2C_INSTANCE);
|
|
|
|
/**
|
|
\brief OV5647 Camera Sensor slave i2c Configuration
|
|
\ref CAMERA_SENSOR_SLAVE_I2C_CONFIG
|
|
*/
|
|
static CAMERA_SENSOR_SLAVE_I2C_CONFIG OV5647_camera_sensor_i2c_cnfg =
|
|
{
|
|
.drv_i2c = &ARM_Driver_I2C_(RTE_OV5647_CAMERA_SENSOR_I2C_INSTANCE),
|
|
.bus_speed = ARM_I2C_BUS_SPEED_STANDARD,
|
|
.cam_sensor_slave_addr = OV5647_CAMERA_SENSOR_SLAVE_ADDR,
|
|
.cam_sensor_slave_reg_addr_type = CAMERA_SENSOR_I2C_REG_ADDR_TYPE_16BIT,
|
|
};
|
|
|
|
static const OV5647_REG sensor_oe_disable_regs[] = {
|
|
{0x3000, 0x00},
|
|
{0x3001, 0x00},
|
|
{0x3002, 0x00},
|
|
};
|
|
|
|
static const OV5647_REG sensor_oe_enable_regs[] = {
|
|
{0x3000, 0x0f},
|
|
{0x3001, 0xff},
|
|
{0x3002, 0xe4},
|
|
};
|
|
|
|
/**
|
|
\brief OV5647 Camera Sensor Resolution 640x480
|
|
*/
|
|
static const OV5647_REG ov5647_640x480_10bpp[] = {
|
|
{0x0100, 0x00},
|
|
{0x0103, 0x01},
|
|
{0x3034, 0x08},
|
|
{0x3035, 0x11},
|
|
{0x3036, 0x46},
|
|
{0x303c, 0x11},
|
|
{0x3821, 0x07},
|
|
{0x3820, 0x41},
|
|
{0x370c, 0x03},
|
|
{0x3612, 0x59},
|
|
{0x3618, 0x00},
|
|
{0x5000, 0x06},
|
|
{0x5001, 0x01},
|
|
{0x5002, 0x41},
|
|
{0x5003, 0x08},
|
|
{0x5a00, 0x08},
|
|
{0x3000, 0xff},
|
|
{0x3001, 0xff},
|
|
{0x3002, 0xff},
|
|
{0x301d, 0xf0},
|
|
{0x3a18, 0x00},
|
|
{0x3a19, 0xf8},
|
|
{0x3c01, 0x80},
|
|
{0x3b07, 0x0c},
|
|
{0x380c, 0x07},
|
|
{0x380d, 0x3c},
|
|
{0x3814, 0x35},
|
|
{0x3815, 0x35},
|
|
{0x3708, 0x64},
|
|
{0x3709, 0x52},
|
|
{0x3808, 0x02},
|
|
{0x3809, 0x80},
|
|
{0x380a, 0x01},
|
|
{0x380b, 0xe0},
|
|
{0x3800, 0x00},
|
|
{0x3801, 0x10},
|
|
{0x3802, 0x00},
|
|
{0x3803, 0x00},
|
|
{0x3804, 0x0a},
|
|
{0x3805, 0x2f},
|
|
{0x3806, 0x07},
|
|
{0x3807, 0x9f},
|
|
{0x3630, 0x2e},
|
|
{0x3632, 0xe2},
|
|
{0x3633, 0x23},
|
|
{0x3634, 0x44},
|
|
{0x3620, 0x64},
|
|
{0x3621, 0xe0},
|
|
{0x3600, 0x37},
|
|
{0x3704, 0xa0},
|
|
{0x3703, 0x5a},
|
|
{0x3715, 0x78},
|
|
{0x3717, 0x01},
|
|
{0x3731, 0x02},
|
|
{0x370b, 0x60},
|
|
{0x3705, 0x1a},
|
|
{0x3f05, 0x02},
|
|
{0x3f06, 0x10},
|
|
{0x3f01, 0x0a},
|
|
{0x3a08, 0x01},
|
|
{0x3a09, 0x2e},
|
|
{0x3a0a, 0x00},
|
|
{0x3a0b, 0xfb},
|
|
{0x3a0d, 0x02},
|
|
{0x3a0e, 0x01},
|
|
{0x3a0f, 0x58},
|
|
{0x3a10, 0x50},
|
|
{0x3a1b, 0x58},
|
|
{0x3a1e, 0x50},
|
|
{0x3a11, 0x60},
|
|
{0x3a1f, 0x28},
|
|
{0x4001, 0x02},
|
|
{0x4004, 0x02},
|
|
{0x4000, 0x09},
|
|
{0x4050, 0x6e},
|
|
{0x4051, 0x8f},
|
|
{0x3000, 0x00},
|
|
{0x3001, 0x00},
|
|
{0x3002, 0x00},
|
|
{0x3017, 0xe0},
|
|
{0x301c, 0xfc},
|
|
{0x3636, 0x06},
|
|
{0x3016, 0x08},
|
|
{0x3827, 0xec},
|
|
{0x3018, 0x44},
|
|
{0x3035, 0x21},
|
|
{0x3106, 0xf5},
|
|
{0x3034, 0x1a},
|
|
{0x301c, 0xf8},
|
|
{0x350a, 0x01},
|
|
{0x350b, 0x8f},
|
|
{0x3500, 0x00},
|
|
{0x3501, 0x0F},
|
|
{0x3502, 0xFF},
|
|
{0x0100, 0x01},
|
|
};
|
|
|
|
/**
|
|
\fn int32_t OV5647_Bulk_Write_Reg(const OV5647_REG OV5647_reg[],
|
|
uint32_t total_num, uint32_t reg_size))
|
|
\brief write array of registers value to OV5647 Camera Sensor registers.
|
|
\param[in] OV5647_reg : OV5647 Camera Sensor Register Array Structure
|
|
\ref OV5647_REG
|
|
\param[in] total_num : total number of registers(size of array)
|
|
\param[in] reg_size : register size in bytes.
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Bulk_Write_Reg(const OV5647_REG OV5647_reg[],
|
|
uint32_t total_num, uint32_t reg_size)
|
|
{
|
|
uint32_t i = 0;
|
|
int32_t ret = 0;
|
|
|
|
for(i = 0; i < total_num; i++)
|
|
{
|
|
ret = OV5647_WRITE_REG(OV5647_reg[i].reg_addr, OV5647_reg[i].reg_value, \
|
|
reg_size);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
}
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Camera_Hard_Reseten(void)
|
|
\brief Hard Reset OV5647 Camera Sensor
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Camera_Hard_Reseten(void)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
ret = GPIO_Driver_CAM_RST->Initialize(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO, NULL);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->PowerControl(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO, ARM_POWER_FULL);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->SetDirection(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO, GPIO_PIN_DIRECTION_OUTPUT);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->SetValue(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO, GPIO_PIN_OUTPUT_STATE_HIGH);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
OV5647_DELAY_uSEC(20000);
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Stream_On(void)
|
|
\brief Start streaming OV5647 Camera Sensor
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Stream_On(void)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
ret = OV5647_WRITE_REG(OV5647_REG_MIPI_CTRL00,
|
|
MIPI_CTRL00_CLOCK_LANE_GATE |
|
|
MIPI_CTRL00_BUS_IDLE |
|
|
MIPI_CTRL00_LINE_SYNC_ENABLE, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = OV5647_WRITE_REG(OV5647_REG_FRAME_OFF_NUMBER, 0x00, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
return OV5647_WRITE_REG(OV5640_REG_PAD_OUT, 0x00, 1);
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Stream_Off(void)
|
|
\brief Stop streaming OV5647 Camera Sensor
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Stream_Off(void)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
ret = OV5647_WRITE_REG(OV5647_REG_MIPI_CTRL00,
|
|
MIPI_CTRL00_CLOCK_LANE_GATE |
|
|
MIPI_CTRL00_BUS_IDLE |
|
|
MIPI_CTRL00_CLOCK_LANE_DISABLE, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = OV5647_WRITE_REG(OV5647_REG_FRAME_OFF_NUMBER, 0x0F, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
return OV5647_WRITE_REG(OV5640_REG_PAD_OUT, 0x01, 1);
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Init(void)
|
|
\brief Initialize OV5647 Camera Sensor
|
|
this function will
|
|
- initialize i2c instance
|
|
- software reset OV5647 Camera Sensor
|
|
- read OV5647 chip-id, proceed only it is correct.
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Init(void)
|
|
{
|
|
int32_t ret = 0;
|
|
uint32_t rcv_data = 0;
|
|
|
|
/*camera sensor resten*/
|
|
ret = OV5647_Camera_Hard_Reseten();
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* Initialize i2c using i3c driver instance depending on
|
|
* OV5647 Camera Sensor specific i2c configurations
|
|
* \ref OV5647_camera_sensor_i2c_cnfg
|
|
*/
|
|
ret = camera_sensor_i2c_init(&OV5647_camera_sensor_i2c_cnfg);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* Read OV5647 Camera Sensor CHIP ID */
|
|
ret = OV5647_READ_REG(OV5647_REG_CHIPID_H, &rcv_data, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
uint16_t chipid = rcv_data << 8;
|
|
|
|
ret = OV5647_READ_REG(OV5647_REG_CHIPID_L, &rcv_data, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
chipid |= rcv_data;
|
|
|
|
/* Proceed only if CHIP ID is correct. */
|
|
if(chipid != OV5647_CHIP_ID_REGISTER_VALUE)
|
|
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
|
|
|
ret = OV5647_WRITE_REG(OV5647_SW_RESET, 0x00, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = OV5647_Bulk_Write_Reg(sensor_oe_enable_regs,
|
|
ARRAY_SIZE(sensor_oe_enable_regs),
|
|
1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
return OV5647_Stream_Off();
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Start(void)
|
|
\brief Start OV5647 Camera Sensor Streaming.
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Start(void)
|
|
{
|
|
/* Start streaming */
|
|
return OV5647_Stream_On();
|
|
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Stop(void)
|
|
\brief Stop OV5647 Camera Sensor Streaming.
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Stop(void)
|
|
{
|
|
/* Suspend any stream */
|
|
return OV5647_Stream_Off();
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Control(uint32_t control, uint32_t arg)
|
|
\brief Control OV5647 Camera Sensor.
|
|
\param[in] control : Operation
|
|
\param[in] arg : Argument of operation
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Control(uint32_t control, uint32_t arg)
|
|
{
|
|
switch (control)
|
|
{
|
|
case CPI_CAMERA_SENSOR_CONFIGURE:
|
|
return OV5647_Bulk_Write_Reg(ov5647_640x480_10bpp, ARRAY_SIZE(ov5647_640x480_10bpp), 1);
|
|
break;
|
|
default:
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
/**
|
|
\fn int32_t OV5647_Uninit(void)
|
|
\brief Un-initialize OV5647 Camera Sensor.
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t OV5647_Uninit(void)
|
|
{
|
|
int32_t ret;
|
|
|
|
ret = OV5647_Bulk_Write_Reg(sensor_oe_disable_regs,
|
|
ARRAY_SIZE(sensor_oe_disable_regs),
|
|
1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->SetValue(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO, GPIO_PIN_OUTPUT_STATE_LOW);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->PowerControl(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO, ARM_POWER_OFF);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
return GPIO_Driver_CAM_RST->Uninitialize(RTE_OV5647_CAMERA_SENSOR_RESET_PIN_NO);
|
|
}
|
|
|
|
/**
|
|
\brief OV5647 Camera Sensor CSI informations
|
|
\ref CSI_INFO
|
|
*/
|
|
static CSI_INFO OV5647_csi_info =
|
|
{
|
|
.frequency = RTE_OV5647_CAMERA_SENSOR_CSI_FREQ,
|
|
.dt = RTE_OV5647_CAMERA_SENSOR_CSI_DATA_TYPE,
|
|
.n_lanes = RTE_OV5647_CAMERA_SENSOR_CSI_N_LANES,
|
|
.vc_id = RTE_OV5647_CAMERA_SENSOR_CSI_VC_ID,
|
|
.cpi_cfg.override = RTE_OV5647_CAMERA_SENSOR_OVERRIDE_CPI_COLOR_MODE,
|
|
.cpi_cfg.cpi_color_mode = RTE_OV5647_CAMERA_SENSOR_CPI_COLOR_MODE
|
|
};
|
|
|
|
/**
|
|
\brief OV5647 Camera Sensor Operations
|
|
\ref CAMERA_SENSOR_OPERATIONS
|
|
*/
|
|
static CAMERA_SENSOR_OPERATIONS OV5647_ops =
|
|
{
|
|
.Init = OV5647_Init,
|
|
.Uninit = OV5647_Uninit,
|
|
.Start = OV5647_Start,
|
|
.Stop = OV5647_Stop,
|
|
.Control = OV5647_Control,
|
|
};
|
|
|
|
/**
|
|
\brief OV5647 Camera Sensor Device Structure
|
|
\ref CAMERA_SENSOR_DEVICE
|
|
*/
|
|
static CAMERA_SENSOR_DEVICE OV5647_camera_sensor =
|
|
{
|
|
.interface = CAMERA_SENSOR_INTERFACE_MIPI,
|
|
.width = RTE_OV5647_CAMERA_SENSOR_FRAME_WIDTH,
|
|
.height = RTE_OV5647_CAMERA_SENSOR_FRAME_HEIGHT,
|
|
.csi_info = &OV5647_csi_info,
|
|
.ops = &OV5647_ops,
|
|
};
|
|
|
|
/* Registering CPI sensor */
|
|
CAMERA_SENSOR(OV5647_camera_sensor)
|
|
|
|
#endif /* RTE_OV5647_CAMERA_SENSOR_ENABLE */
|