mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
759 lines
25 KiB
C
759 lines
25 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"
|
|
#include "sys_ctrl_cpi.h"
|
|
|
|
/* Proceed only if AR0145 Camera Sensor is enabled. */
|
|
#if RTE_AR0145_CAMERA_SENSOR_CSI_ENABLE
|
|
|
|
/* I2C Instance */
|
|
#if(RTE_AR0145_CAMERA_SENSOR_I2C_INSTANCE == 4)
|
|
#define CAMERA_SENSOR_I2C_INSTANCE I3C
|
|
#else
|
|
#define CAMERA_SENSOR_I2C_INSTANCE RTE_AR0145_CAMERA_SENSOR_I2C_INSTANCE
|
|
#endif
|
|
|
|
/* Image Configuration */
|
|
#if (RTE_AR0145_CAMERA_SENSOR_IMAGE_CONFIG == 0)
|
|
#define AR0145_CAMERA_SENSOR_FRAME_HEIGHT 800
|
|
#define AR0145_CAMERA_SENSOR_FRAME_WIDTH 1280
|
|
#elif ((RTE_AR0145_CAMERA_SENSOR_IMAGE_CONFIG == 1) || (RTE_AR0145_CAMERA_SENSOR_IMAGE_CONFIG == 2))
|
|
#define AR0145_CAMERA_SENSOR_FRAME_HEIGHT 400
|
|
#define AR0145_CAMERA_SENSOR_FRAME_WIDTH 640
|
|
#elif (RTE_AR0145_CAMERA_SENSOR_IMAGE_CONFIG == 3)
|
|
#define AR0145_CAMERA_SENSOR_FRAME_HEIGHT 200
|
|
#define AR0145_CAMERA_SENSOR_FRAME_WIDTH 320
|
|
#else
|
|
#error Unsupported resolution
|
|
#endif
|
|
|
|
/* AR0145 Camera Sensor Slave Address. */
|
|
#define AR0145_CAMERA_SENSOR_SLAVE_ADDR 0x36
|
|
|
|
/* AR0145 Camera Sensor CHIP-ID registers */
|
|
#define AR0145_CHIP_ID_REGISTER 0x3000
|
|
#define AR0145_CHIP_ID_REGISTER_VALUE 0x1750
|
|
|
|
/* AR0145 Camera Sensor registers index */
|
|
#define AR0145_RESET_REGISTER 0x301A
|
|
#define AR0145_MIPI_CONFIG_REGISTER 0x31BE
|
|
#define AR0145_COARSE_INTEGRATION_TIME_REGISTER 0x0202
|
|
#define AR0145_GLOBAL_GAIN_REGISTER 0x305E
|
|
#define AR0145_X_ADDR_END_REGISTER 0x3008
|
|
#define AR0145_Y_ADDR_END_REGISTER 0x3006
|
|
#define AR0145_X_EVEN_INC_REGISTER 0x30A0
|
|
#define AR0145_X_ODD_INC_REGISTER 0x30A2
|
|
#define AR0145_Y_EVEN_INC_REGISTER 0x30A4
|
|
#define AR0145_Y_ODD_INC_REGISTER 0x30A6
|
|
#define AR0145_X_OUTPUT_SIZE_REGISTER 0x034C
|
|
#define AR0145_Y_OUTPUT_SIZE_REGISTER 0x034E
|
|
#define AR0145_READ_MODE_REGISTER 0x3040
|
|
#define AR0145_SMIA_TEST_REGISTER 0x3064
|
|
#define AR0145_DATAPATH_SELECT_REGISTER 0x306E
|
|
#define AR0145_AE_MAX_EXPOSURE_REGISTER 0x323A
|
|
#define AR0145_AE_STATS_CONTROL_REGISTER 0x327A
|
|
#define AR0145_AE_CTRL_REGISTER 0x3220
|
|
#define AR0145_AE_LUMA_TARGET_REGISTER 0x3222
|
|
|
|
/* AR0145 Camera Sensor Configurations*/
|
|
#define AR0145_AE_LUMA_TARGET_VALUE 0x6500
|
|
#define AR0145_AE_ENABLE 0x0213
|
|
#define AR0145_AE_DISABLE 0x0200
|
|
#define AR0145_EMBEDDED_STATISTICS_ENABLE 0x0010
|
|
#define AR0145_EMBEDDED_DATA_ENABLE 0x5940
|
|
#define AR0145_EMBEDDED_DATA_SELECT 0x900F
|
|
|
|
|
|
/* Wrapper function for Delay
|
|
* Delay for microsecond:
|
|
* Provide delay using PMU(Performance Monitoring Unit).
|
|
*/
|
|
#define AR0145_DELAY_uSEC(usec) sys_busy_loop_us(usec)
|
|
|
|
/* Wrapper function for i2c read
|
|
* read register value from AR0145 Camera Sensor registers
|
|
* using i2c read API \ref camera_sensor_i2c_read
|
|
*
|
|
* for AR0145 Camera Sensor specific i2c configurations
|
|
* see \ref AR0145_camera_sensor_i2c_cnfg
|
|
*/
|
|
#define AR0145_READ_REG(reg_addr, reg_value, reg_size) \
|
|
camera_sensor_i2c_read(&AR0145_camera_sensor_i2c_cnfg, \
|
|
reg_addr, \
|
|
reg_value, \
|
|
(CAMERA_SENSOR_I2C_REG_SIZE)reg_size)
|
|
|
|
/* Wrapper function for i2c write
|
|
* write register value to AR0145 Camera Sensor registers
|
|
* using i2c write API \ref camera_sensor_i2c_write.
|
|
*
|
|
* for AR0145 Camera Sensor specific i2c configurations
|
|
* see \ref AR0145_camera_sensor_i2c_cnfg
|
|
*/
|
|
#define AR0145_WRITE_REG(reg_addr, reg_value, reg_size) \
|
|
camera_sensor_i2c_write(&AR0145_camera_sensor_i2c_cnfg, \
|
|
reg_addr, \
|
|
reg_value, \
|
|
(CAMERA_SENSOR_I2C_REG_SIZE)reg_size)
|
|
|
|
static uint32_t current_integration_time;
|
|
static uint32_t max_integration_time;
|
|
|
|
/* AR0145 Camera reset GPIO port */
|
|
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_AR0145_CAMERA_SENSOR_RESET_GPIO_PORT);
|
|
static ARM_DRIVER_GPIO *GPIO_Driver_CAM_RST = &ARM_Driver_GPIO_(RTE_AR0145_CAMERA_SENSOR_RESET_GPIO_PORT);
|
|
|
|
/* AR0145 Camera power GPIO port */
|
|
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_AR0145_CAMERA_SENSOR_POWER_GPIO_PORT);
|
|
static ARM_DRIVER_GPIO *GPIO_Driver_CAM_PWR = &ARM_Driver_GPIO_(RTE_AR0145_CAMERA_SENSOR_POWER_GPIO_PORT);
|
|
|
|
/* I2C Driver Instance */
|
|
extern ARM_DRIVER_I2C ARM_Driver_I2C_(CAMERA_SENSOR_I2C_INSTANCE);
|
|
|
|
/**
|
|
\brief AR0145 Camera Sensor Register Array Structure
|
|
used for Camera Resolution Configuration.
|
|
*/
|
|
typedef struct _AR0145_REG {
|
|
uint16_t reg_addr; /* AR0145 Camera Sensor Register Address*/
|
|
uint16_t reg_value; /* AR0145 Camera Sensor Register Value*/
|
|
} AR0145_REG;
|
|
|
|
/**
|
|
\brief AR0145 Camera Sensor slave i2c Configuration
|
|
\ref CAMERA_SENSOR_SLAVE_I2C_CONFIG
|
|
*/
|
|
static CAMERA_SENSOR_SLAVE_I2C_CONFIG AR0145_camera_sensor_i2c_cnfg =
|
|
{
|
|
.drv_i2c = &ARM_Driver_I2C_(CAMERA_SENSOR_I2C_INSTANCE),
|
|
.bus_speed = ARM_I2C_BUS_SPEED_STANDARD,
|
|
.cam_sensor_slave_addr = AR0145_CAMERA_SENSOR_SLAVE_ADDR,
|
|
.cam_sensor_slave_reg_addr_type = CAMERA_SENSOR_I2C_REG_ADDR_TYPE_16BIT,
|
|
};
|
|
|
|
static const AR0145_REG cfg_8bit_2Lane_Pxlclk80MHz_Extclk25MHz[] = {
|
|
{ 0x301A, 0x0019 }, // RESET_REGISTER
|
|
{ 0xFFFF, 0x2 }, // DELAY= 200
|
|
{ 0x0300, 0x0005 }, // VT_PIX_CLK_DIV
|
|
{ 0x0302, 0x0001 }, // VT_SYS_CLK_DIV
|
|
{ 0x0304, 0x0505 }, // PRE_PLL_CLK_DIV
|
|
{ 0x0306, 0x8050 }, // PLL_MULTIPLIER
|
|
{ 0x0308, 0x0008 }, // OP_PIX_CLK_DIV
|
|
{ 0x030A, 0x0001 }, // OP_SYS_CLK_DIV
|
|
{ 0x0344, 0x0008 }, // X_ADDR_START
|
|
{ 0x0346, 0x0008 }, // Y_ADDR_START
|
|
{ 0x3040, 0x0000 }, // READ_MODE
|
|
{ 0x0400, 0x0000 }, // SCALING_MODE
|
|
{ 0x0404, 0x0010 }, // SCALE_M
|
|
{ 0x0342, 0x0640 }, // LINE_LENGTH_PCK
|
|
{ 0x0340, 0x0340 }, // FRAME_LENGTH_LINES
|
|
{ 0x0112, 0x0808 }, // CCP_DATA_FORMAT
|
|
{ 0x31B0, 0x0041 }, // FRAME_PREAMBLE
|
|
{ 0x31B2, 0x0024 }, // LINE_PREAMBLE
|
|
{ 0x31B4, 0x320A }, // MIPI_TIMING_0
|
|
{ 0x31B6, 0x32E6 }, // MIPI_TIMING_1
|
|
{ 0x31B8, 0x1412 }, // MIPI_TIMING_2
|
|
{ 0x31BA, 0x1442 }, // MIPI_TIMING_3
|
|
{ 0x31BC, 0x8407 }, // MIPI_TIMING_4
|
|
|
|
};
|
|
|
|
/**
|
|
\fn int32_t AR0145_Bulk_Write_Reg(const AR0145_REG AR0145_reg[],
|
|
uint32_t total_num, uint32_t reg_size))
|
|
\brief write array of registers value to AR0145 Camera Sensor registers.
|
|
\param[in] AR0145_reg : AR0145 Camera Sensor Register Array Structure
|
|
\ref AR0145_REG
|
|
\param[in] total_num : total number of registers(size of array)
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t AR0145_Bulk_Write_Reg(const AR0145_REG AR0145_reg[],
|
|
uint32_t total_num, uint32_t reg_size)
|
|
{
|
|
uint32_t i = 0;
|
|
int32_t ret = 0;
|
|
|
|
for(i = 0; i < total_num; i++)
|
|
{
|
|
if (0xFFFF == AR0145_reg[i].reg_addr) {
|
|
for(uint32_t j = 0; j < AR0145_reg[i].reg_value ; j++)
|
|
{
|
|
AR0145_DELAY_uSEC(100 * 1000);
|
|
}
|
|
continue;
|
|
}
|
|
ret = AR0145_WRITE_REG(AR0145_reg[i].reg_addr, AR0145_reg[i].reg_value, \
|
|
reg_size);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
}
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn void AR0145_Sensor_Enable_Clk_Src(void)
|
|
\brief Enable AR0145 Camera Sensor external clock source configuration.
|
|
\param[in] none
|
|
\return none
|
|
*/
|
|
static void AR0145_Sensor_Enable_Clk_Src(void)
|
|
{
|
|
set_cpi_pixel_clk(CPI_PIX_CLKSEL_400MZ, RTE_AR0145_CAMERA_SENSOR_CSI_CLK_SCR_DIV);
|
|
}
|
|
|
|
/**
|
|
\fn void AR0145_Sensor_Disable_Clk_Src(void)
|
|
\brief Disable AR0145 Camera Sensor external clock source configuration.
|
|
\param[in] none
|
|
\return none
|
|
*/
|
|
static void AR0145_Sensor_Disable_Clk_Src(void)
|
|
{
|
|
clear_cpi_pixel_clk();
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Camera_Hard_Reseten(void)
|
|
\brief Hard Reset AR0145 Camera Sensor
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t AR0145_Camera_Hard_Reseten(void)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
ret = GPIO_Driver_CAM_RST->Initialize(RTE_AR0145_CAMERA_SENSOR_RESET_PIN_NO, NULL);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->PowerControl(RTE_AR0145_CAMERA_SENSOR_RESET_PIN_NO, ARM_POWER_FULL);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->SetDirection(RTE_AR0145_CAMERA_SENSOR_RESET_PIN_NO, GPIO_PIN_DIRECTION_OUTPUT);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_PWR->Initialize(RTE_AR0145_CAMERA_SENSOR_POWER_PIN_NO, NULL);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_PWR->PowerControl(RTE_AR0145_CAMERA_SENSOR_POWER_PIN_NO, ARM_POWER_FULL);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_PWR->SetDirection(RTE_AR0145_CAMERA_SENSOR_POWER_PIN_NO, GPIO_PIN_DIRECTION_OUTPUT);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = GPIO_Driver_CAM_RST->SetValue(RTE_AR0145_CAMERA_SENSOR_RESET_PIN_NO, GPIO_PIN_OUTPUT_STATE_LOW);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
AR0145_DELAY_uSEC(2000);
|
|
|
|
ret = GPIO_Driver_CAM_PWR->SetValue(RTE_AR0145_CAMERA_SENSOR_POWER_PIN_NO, GPIO_PIN_OUTPUT_STATE_HIGH);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
AR0145_DELAY_uSEC(1000);
|
|
|
|
ret = GPIO_Driver_CAM_RST->SetValue(RTE_AR0145_CAMERA_SENSOR_RESET_PIN_NO, GPIO_PIN_OUTPUT_STATE_HIGH);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
AR0145_DELAY_uSEC(100000);
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Camera_Soft_Reseten(void)
|
|
\brief Software Reset AR0145 Camera Sensor
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t AR0145_Camera_Soft_Reseten(void)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_RESET_REGISTER, 0x01, 1);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* @Observation: more delay is required for Camera Sensor
|
|
* to setup after Soft Reset.
|
|
*/
|
|
AR0145_DELAY_uSEC(10000);
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Sensor_Configuration(void)
|
|
\brief AR0145 Camera Sensor configuration
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
int32_t AR0145_Sensor_Configuration(void)
|
|
{
|
|
int32_t ret;
|
|
uint32_t total_num, skip = 1280 / AR0145_CAMERA_SENSOR_FRAME_WIDTH;
|
|
|
|
total_num = (sizeof(cfg_8bit_2Lane_Pxlclk80MHz_Extclk25MHz) / sizeof(AR0145_REG));
|
|
ret = AR0145_Bulk_Write_Reg(cfg_8bit_2Lane_Pxlclk80MHz_Extclk25MHz, total_num, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_X_ADDR_END_REGISTER, 1287 - (skip - 1), 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_Y_ADDR_END_REGISTER, 807 - (skip - 1), 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_X_EVEN_INC_REGISTER, skip, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
ret = AR0145_WRITE_REG(AR0145_X_ODD_INC_REGISTER, skip, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
ret = AR0145_WRITE_REG(AR0145_Y_EVEN_INC_REGISTER, skip, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
ret = AR0145_WRITE_REG(AR0145_Y_ODD_INC_REGISTER, skip, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_X_OUTPUT_SIZE_REGISTER, AR0145_CAMERA_SENSOR_FRAME_WIDTH, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
ret = AR0145_WRITE_REG(AR0145_Y_OUTPUT_SIZE_REGISTER, AR0145_CAMERA_SENSOR_FRAME_HEIGHT, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_COARSE_INTEGRATION_TIME_REGISTER, AR0145_CAMERA_SENSOR_FRAME_HEIGHT + 31, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
#if(RTE_AR0145_CAMERA_SENSOR_IMAGE_CONFIG == 1)
|
|
uint32_t rcv_data;
|
|
ret = AR0145_READ_REG(AR0145_READ_MODE_REGISTER, &rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_READ_MODE_REGISTER, rcv_data | (1U << 11) | (1U << 13), 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
#endif
|
|
|
|
max_integration_time = current_integration_time = 0;
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Camera_Gain(uint32_t gain)
|
|
\brief Set camera gain
|
|
this function will
|
|
- configure Camera Sensor gain and integration time as per input parameter.
|
|
|
|
Gain 1 is the default integration time with camera gain set to 1.
|
|
|
|
For requested gain > 1, we use the default integration time and adjust the analogue+digital gain.
|
|
For requested gain < 1, we set gain to 1 and use a reduced integration time.
|
|
|
|
\note This has been adapted to AR0145 from ARX3A0
|
|
\param[in] gain : gain value * 65536 (so 1.0 gain = 65536); 0 to read
|
|
\return \ref actual gain
|
|
*/
|
|
static int32_t AR0145_Camera_Gain(const uint32_t gain)
|
|
{
|
|
uint32_t digital_gain;
|
|
uint32_t fine_gain = gain;
|
|
uint32_t coarse_gain;
|
|
uint32_t t,s;
|
|
|
|
if (max_integration_time == 0)
|
|
{
|
|
/* Record the integration time set by the configuration tables. We won't adjust it upwards, as it may
|
|
* interfere with frame timing, but we can freely adjust it downwards.
|
|
*/
|
|
int32_t ret = AR0145_READ_REG(AR0145_COARSE_INTEGRATION_TIME_REGISTER, ¤t_integration_time, 2);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
max_integration_time = current_integration_time;
|
|
}
|
|
|
|
if (gain != 0)
|
|
{
|
|
/* Request to set gain */
|
|
|
|
/* From the Design Guide:
|
|
*
|
|
* First clamp analogue gain, using digital gain to get more if
|
|
* necessary. Otherwise digital gain is used to fine adjust.
|
|
*/
|
|
uint32_t new_integration_time = max_integration_time;
|
|
if (gain < 0x10000)
|
|
{
|
|
/* Minimum gain is 1.0 */
|
|
fine_gain = 0x10000;
|
|
|
|
/* But we can lower integration time */
|
|
new_integration_time = (uint32_t) (((float) max_integration_time * gain) * 0x1p-16f + 0.5f);
|
|
}
|
|
else if (gain > 0x80000)
|
|
{
|
|
/* Maximum analogue gain is 8.0 */
|
|
fine_gain = 0x80000;
|
|
}
|
|
|
|
/* Set integration time */
|
|
if (new_integration_time != current_integration_time)
|
|
{
|
|
int32_t ret = AR0145_WRITE_REG(AR0145_COARSE_INTEGRATION_TIME_REGISTER, new_integration_time, 2);
|
|
if (ret != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
current_integration_time = new_integration_time;
|
|
}
|
|
|
|
/*
|
|
* First get coarse analogue power of two, leaving fine gain in range [0x10000,0x1FFFF]
|
|
*/
|
|
s = 0;
|
|
while (fine_gain >= 0x20000)
|
|
{
|
|
s++;
|
|
fine_gain /= 2;
|
|
}
|
|
|
|
/* Fine gain is produced as 1 + (t / 16), roughly. Rearranged, t = 16(fine_gain - 1)*/
|
|
/* Ensure we round down, by rounding up the division */
|
|
t = 16 * ((fine_gain / 0x10000) - 1);
|
|
|
|
/* Use digital gain to extend gain beyond the analogue limits of
|
|
* x1 to x8, or to fine-tune within that range.
|
|
*
|
|
* We don't let digital gain go below 1.0 - it just loses information,
|
|
* and clamping it lets an auto-gain controller see that we are
|
|
* unable to improve exposure by such lowering. Another camera might
|
|
* be able to usefully set gain to <1.0, so a controller could try it.
|
|
*
|
|
* (When we're fine tuning, digital gain is always >=1.0, because we
|
|
* round down analogue gain, so it can only go below 1.0 by the user
|
|
* requesting total gain < 1.0).
|
|
*/
|
|
|
|
/* coarse_gain = 2^s, Total analog gain = coarse_gain * (1 + t / 16) */
|
|
coarse_gain = (1 << s);
|
|
float resulting_analogue_gain = coarse_gain * (1 + (t)/16.f);
|
|
|
|
digital_gain = (uint32_t) ((0x1p5f * 0x1p-16f * gain) / resulting_analogue_gain + 0.5f);
|
|
if (digital_gain > 0x1FF)
|
|
{
|
|
/* Maximum digital gain is just under 16.0 (limited by register size) */
|
|
digital_gain = 0x1FF;
|
|
}
|
|
else if (digital_gain < 32)
|
|
{
|
|
/* Digital gain >= 1.0, as per discussion above */
|
|
digital_gain = 32;
|
|
}
|
|
int32_t ret = AR0145_WRITE_REG(AR0145_GLOBAL_GAIN_REGISTER, (digital_gain << 7) |(s << 4) | t, 2);
|
|
if (ret != 0)
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
uint32_t reg_value;
|
|
|
|
int32_t ret = AR0145_READ_REG(AR0145_GLOBAL_GAIN_REGISTER, ®_value, 2);
|
|
if (ret != 0)
|
|
return ret;
|
|
digital_gain = (reg_value >> 7) & 0x1FF;
|
|
s = (reg_value >> 4) & 7;
|
|
t = reg_value & 0xF;
|
|
coarse_gain = (1 << s);
|
|
}
|
|
|
|
float resulting_gain = coarse_gain * (1 + (t)/16.f) * (digital_gain * 0x1p-5f);
|
|
|
|
// And adjust for any reduction of integration time (in which case gain should be 0x10000 initially...)
|
|
if (current_integration_time != max_integration_time)
|
|
{
|
|
resulting_gain = ((resulting_gain * current_integration_time) / max_integration_time + 0.5f);
|
|
}
|
|
return (uint32_t) (resulting_gain * 0x1p16f + 0.5f);
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Camera_AE(const uint32_t enable)
|
|
\brief Set camera Auto Exposure
|
|
\param[in] enable: 0=disable, 1=enable
|
|
\return \ref execution_statusn
|
|
*/
|
|
static int32_t AR0145_Camera_AE(const uint32_t enable)
|
|
{
|
|
int32_t ret = 0;
|
|
if(enable)
|
|
{
|
|
uint32_t rcv_data = 0;
|
|
ret = AR0145_READ_REG(AR0145_COARSE_INTEGRATION_TIME_REGISTER, &rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_AE_MAX_EXPOSURE_REGISTER, rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_AE_STATS_CONTROL_REGISTER, AR0145_EMBEDDED_STATISTICS_ENABLE, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_SMIA_TEST_REGISTER, AR0145_EMBEDDED_DATA_ENABLE, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_DATAPATH_SELECT_REGISTER, AR0145_EMBEDDED_DATA_SELECT, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_AE_CTRL_REGISTER, AR0145_AE_ENABLE, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_AE_LUMA_TARGET_REGISTER, AR0145_AE_LUMA_TARGET_VALUE, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
ret = AR0145_WRITE_REG(AR0145_AE_CTRL_REGISTER, AR0145_AE_DISABLE, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
}
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Init(void)
|
|
\brief Initialize AR0145 Camera Sensor
|
|
this function will
|
|
- initialize i2c using i3c instance
|
|
- software reset AR0145 Camera Sensor
|
|
- read AR0145 chip-id, proceed only it is correct.
|
|
\return \ref execution_status
|
|
*/
|
|
int32_t AR0145_Init(void)
|
|
{
|
|
int32_t ret = 0;
|
|
uint32_t rcv_data = 0;
|
|
|
|
/*Enable camera sensor clock source config*/
|
|
AR0145_Sensor_Enable_Clk_Src();
|
|
|
|
/*camera sensor resten*/
|
|
ret = AR0145_Camera_Hard_Reseten();
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* Initialize i2c using i3c driver instance depending on
|
|
* AR0145 Camera Sensor specific i2c configurations
|
|
* \ref AR0145_camera_sensor_i2c_cnfg
|
|
*/
|
|
ret = camera_sensor_i2c_init(&AR0145_camera_sensor_i2c_cnfg);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* Soft Reset AR0145 Camera Sensor */
|
|
ret = AR0145_Camera_Soft_Reseten();
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* Read AR0145 Camera Sensor CHIP ID */
|
|
ret = AR0145_READ_REG(AR0145_CHIP_ID_REGISTER, &rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/* Proceed only if CHIP ID is correct. */
|
|
if(rcv_data != AR0145_CHIP_ID_REGISTER_VALUE)
|
|
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
|
|
|
/* Enable LP11 on standby */
|
|
ret = AR0145_READ_REG(AR0145_MIPI_CONFIG_REGISTER, &rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_MIPI_CONFIG_REGISTER, rcv_data | (1U << 7), 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/*start streaming*/
|
|
ret = AR0145_READ_REG(AR0145_RESET_REGISTER, &rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_RESET_REGISTER, rcv_data | (1U << 2), 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
AR0145_DELAY_uSEC(50000);
|
|
|
|
/*stop streaming*/
|
|
ret = AR0145_WRITE_REG(AR0145_RESET_REGISTER, rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
/*Adding delay to finish streaming*/
|
|
AR0145_DELAY_uSEC(500000);
|
|
|
|
/* Force re-reading of the registers */
|
|
max_integration_time = current_integration_time = 0;
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Start(void)
|
|
\brief Start AR0145 Camera Sensor Streaming.
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
int32_t AR0145_Start(void)
|
|
{
|
|
int32_t ret = 0;
|
|
uint32_t rcv_data = 0;
|
|
|
|
/* Start streaming */
|
|
ret = AR0145_READ_REG(AR0145_RESET_REGISTER, &rcv_data, 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
ret = AR0145_WRITE_REG(AR0145_RESET_REGISTER, rcv_data | (1U << 2), 2);
|
|
if(ret != ARM_DRIVER_OK)
|
|
return ret;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Stop(void)
|
|
\brief Stop AR0145 Camera Sensor Streaming.
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
int32_t AR0145_Stop(void)
|
|
{
|
|
/* Suspend any stream */
|
|
return AR0145_WRITE_REG(AR0145_RESET_REGISTER, 0x00, 1);
|
|
}
|
|
|
|
/**
|
|
\fn int32_t AR0145_Control(uint32_t control, uint32_t arg)
|
|
\brief Control AR0145 Camera Sensor.
|
|
\param[in] control : Operation
|
|
\param[in] arg : Argument of operation
|
|
\return \ref execution_status
|
|
*/
|
|
int32_t AR0145_Control(uint32_t control, uint32_t arg)
|
|
{
|
|
switch (control)
|
|
{
|
|
case CPI_CAMERA_SENSOR_CONFIGURE:
|
|
return AR0145_Sensor_Configuration();
|
|
case CPI_CAMERA_SENSOR_GAIN:
|
|
return AR0145_Camera_Gain(arg);
|
|
case CPI_CAMERA_SENSOR_AE:
|
|
return AR0145_Camera_AE(arg);
|
|
case CPI_CAMERA_SENSOR_AE_TARGET_LUMA:
|
|
/* Legal values: [0, 65535]. To set to 1/2 saturation, value should be set to 0x8000. */
|
|
return AR0145_WRITE_REG(AR0145_AE_LUMA_TARGET_REGISTER, arg, 2);
|
|
default:
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
}
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
\fn int32_t AR0145_Uninit(void)
|
|
\brief Un-initialize AR0145 Camera Sensor.
|
|
\param[in] none
|
|
\return \ref execution_status
|
|
*/
|
|
int32_t AR0145_Uninit(void)
|
|
{
|
|
|
|
/*Disable camera sensor clock source config*/
|
|
AR0145_Sensor_Disable_Clk_Src();
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\brief AR0145 Camera Sensor CSi informations
|
|
\ref CSI_INFO
|
|
*/
|
|
static CSI_INFO AR0145_csi_info =
|
|
{
|
|
.frequency = RTE_AR0145_CAMERA_SENSOR_CSI_FREQ,
|
|
.dt = RTE_AR0145_CAMERA_SENSOR_CSI_DATA_TYPE,
|
|
.n_lanes = RTE_AR0145_CAMERA_SENSOR_CSI_N_LANES,
|
|
.vc_id = RTE_AR0145_CAMERA_SENSOR_CSI_VC_ID,
|
|
.cpi_cfg.override = RTE_AR0145_CAMERA_SENSOR_OVERRIDE_CPI_COLOR_MODE,
|
|
.cpi_cfg.cpi_color_mode = RTE_AR0145_CAMERA_SENSOR_CPI_COLOR_MODE
|
|
};
|
|
|
|
/**
|
|
\brief AR0145 Camera Sensor Operations
|
|
\ref CAMERA_SENSOR_OPERATIONS
|
|
*/
|
|
static CAMERA_SENSOR_OPERATIONS AR0145_ops =
|
|
{
|
|
.Init = AR0145_Init,
|
|
.Uninit = AR0145_Uninit,
|
|
.Start = AR0145_Start,
|
|
.Stop = AR0145_Stop,
|
|
.Control = AR0145_Control,
|
|
};
|
|
|
|
/**
|
|
\brief AR0145 Camera Sensor Device Structure
|
|
\ref CAMERA_SENSOR_DEVICE
|
|
*/
|
|
static CAMERA_SENSOR_DEVICE AR0145_camera_sensor =
|
|
{
|
|
.interface = CAMERA_SENSOR_INTERFACE_MIPI,
|
|
.width = AR0145_CAMERA_SENSOR_FRAME_WIDTH,
|
|
.height = AR0145_CAMERA_SENSOR_FRAME_HEIGHT,
|
|
.csi_info = &AR0145_csi_info,
|
|
.ops = &AR0145_ops,
|
|
};
|
|
|
|
/* Registering CPI sensor */
|
|
CAMERA_SENSOR(AR0145_camera_sensor)
|
|
|
|
#endif /* RTE_AR0145_CAMERA_SENSOR_ENABLE */
|