37 #include <sys/ioctl.h>
38 #include <linux/i2c-dev.h>
39 #include <linux/videodev2.h>
41 #include "generated/airframe.h"
48 #define PRINT(string,...) fprintf(stderr, "[MT9F002->%s()] " string,__FUNCTION__ , ##__VA_ARGS__)
51 #define VERBOSE_PRINT PRINT
53 #define VERBOSE_PRINT(...)
68 #ifndef MT9F002_TARGET_EXPOSURE
69 #define MT9F002_TARGET_EXPOSURE 30
73 #ifndef MT9F002_GAIN_GREEN1
74 #define MT9F002_GAIN_GREEN1 2.0
77 #ifndef MT9F002_GAIN_GREEN2
78 #define MT9F002_GAIN_GREEN2 2.0
81 #ifndef MT9F002_GAIN_RED
82 #define MT9F002_GAIN_RED 1.4
85 #ifndef MT9F002_GAIN_BLUE
86 #define MT9F002_GAIN_BLUE 2.7
105 .dev_name =
"/dev/video1",
106 .subdev_name =
"/dev/v4l-subdev1",
107 .format = V4L2_PIX_FMT_UYVY,
108 .subdev_format = V4L2_MBUS_FMT_SGRBG10_1X10,
113 .camera_intrinsics = {
126 .input_clk_freq = (26 / 2),
184 }
else if (len == 2) {
187 }
else if (len == 4) {
193 PRINT(
"Write_reg with incorrect length %d\r\n", len);
213 for (
uint8_t i = 0; i < len; i++) {
229 serialFormat = (3 << 8) | 2;
231 serialFormat = (2 << 8) | 2;
646 row_speed = (row_speed & 0xFFF8) | (mt->
rowSpeed_2_0 & 0x07);
647 row_speed = (row_speed & 0xF8FF) | ((mt->
row_speed_10_8 & 0x07) << 8);
648 row_speed = (row_speed & (~0x70)) | (0x2 << 4);
696 float subsamplingX_factor = (float)(1 + mt->
x_odd_inc) / 2.0f;
697 float subsamplingY_factor = (float)(1 + mt->
y_odd_inc) / 2.0f;
710 min_line_length =
Max(min_line_length,
714 min_line_length =
Max(min_line_length,
724 clkRatio_num = clkRatio_num / clkRatio_gcd;
725 clkRatio_den = clkRatio_den / clkRatio_gcd;
728 uint32_t min_horizontal_blanking = clkRatio_num;
729 if ((clkRatio_den % 2) != 0) {
730 min_horizontal_blanking *= 2;
734 if ((min_line_length % min_horizontal_blanking) != 0) {
735 min_line_length += min_horizontal_blanking - (min_line_length % min_horizontal_blanking);
744 uint16_t min_frame_length = (y_addr_end - y_addr_start + 1) / subsamplingY_factor + min_frame_blanking_lines;
760 new_fps = mt->
vt_pix_clk * 1000000 / (float)(ll * fl);
770 if (fps_err < min_fps_err) {
771 min_fps_err = fps_err;
779 new_fps = mt->
vt_pix_clk * 1000000 / (float)(ll * min_frame_length);
814 if (fine_integration_min > fine_integration || fine_integration > fine_integration_max) {
815 int32_t upper_coarse_integration = coarse_integration + 1;
816 int32_t upper_fine_integration = fine_integration_min;
818 int32_t lower_coarse_integration = coarse_integration - 1;
819 int32_t lower_fine_integration = fine_integration_max;
822 if (lower_coarse_integration < coarse_integration_min) {
823 coarse_integration = upper_coarse_integration;
824 fine_integration = upper_fine_integration;
827 else if (upper_coarse_integration > coarse_integration_max) {
828 coarse_integration = lower_coarse_integration;
829 fine_integration = lower_fine_integration;
834 int32_t upper_error = abs((mt->
line_length * upper_coarse_integration + upper_fine_integration) - integration);
835 int32_t lower_error = abs((mt->
line_length * lower_coarse_integration + lower_fine_integration) - integration);
837 if (upper_error < lower_error) {
838 coarse_integration = upper_coarse_integration;
839 fine_integration = upper_fine_integration;
841 coarse_integration = lower_coarse_integration;
842 fine_integration = lower_fine_integration;
848 Bound(fine_integration, fine_integration_min, fine_integration_max);
849 Bound(coarse_integration, coarse_integration_min, coarse_integration_max);
868 uint8_t colamp_gain, analog_gain3, digital_gain;
874 }
else if (gain < 3.0) {
878 }
else if (gain < 6.0) {
882 }
else if (gain < 16.0) {
886 }
else if (gain < 32.0) {
897 uint16_t analog_gain2 = gain / (float)digital_gain / (
float)(1 << colamp_gain) / (
float)(1 << analog_gain3) * 64.0;
898 Bound(analog_gain2, 1, 127);
900 return (analog_gain2 & 0x7F) | ((analog_gain3 & 0x7) << 7) | ((colamp_gain & 0x3) << 10) | ((digital_gain & 0xF) << 12);
916 struct v4l2_rect crop, rect;
917 unsigned int x_odd_inc, y_odd_inc;
918 unsigned int hratio, vratio;
919 unsigned int width, height;
921 unsigned int xMultiple;
922 unsigned int div_res;
923 static const uint8_t xy_odd_inc_tab[] = {1, 1, 3, 3, 7, 7, 7, 7, 15};
931 VERBOSE_PRINT(
"Requested crop - top: %i, left: %i, width: %i, height: %i\n", crop.top, crop.left, crop.width,
945 div_res =
Min(rect.width / width, rect.height / height);
946 div_res = Clip(div_res, 1, 4);
947 x_odd_inc = xy_odd_inc_tab[div_res];
948 y_odd_inc = xy_odd_inc_tab[div_res];
953 ratio =
Min(hratio, vratio);
964 VERBOSE_PRINT(
"Calculated skipping - x: %i, y: %i\n", x_odd_inc, y_odd_inc);
968 rect.left = crop.left + ((
int32_t)crop.width - (
int32_t)rect.width) / 2;
969 rect.top = crop.top + ((
int32_t)crop.height - (
int32_t)rect.height) / 2;
977 xMultiple = 8 * ((x_odd_inc + 1) / 2);
978 rect.left = Align(rect.left, xMultiple);
981 rect.top = Align(rect.top, 4);
985 VERBOSE_PRINT(
"Granted crop - top: %i, left: %i, width: %i, height: %i\n", crop.top, crop.left, crop.width,
987 VERBOSE_PRINT(
"Granted output - width: %i, height: %i\n", width, height);
#define MT9F002_DAC_LD_30_31
uint16_t min_line_blanking_pck
static void mt9f002_parallel_stage2(struct mt9f002_t *mt)
Configure stage 2 for parallel connection.
#define MT9F002_SOFTWARE_RESET
#define CFG_MT9F002_X_ADDR_MAX
void mt9f002_setting_update_exposure(float in)
struct blanking_t mt9f002_blanking
uint16_t fine_integration_time_min
#define MT9F002_X_ADDR_END
float set_zoom
Image zoom set point.
#define MT9F002_FINE_INTEGRATION_TIME_
void mt9f002_set_exposure(struct mt9f002_t *mt)
Set the exposure configuration Depends on the blanking (and therefore the FPS)
#define CFG_MT9F002_Y_ADDR_MIN
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
#define MT9F002_LINE_LENGTH_PCK
uint8_t x_odd_inc
X increment for subsampling (1,3,7,15,31 accepted)
#define MT9F002_MASK_CORRUPTED_FRAMES
#define MT9F002_CTX_WR_DATA_REG
#define MT9F002_MIN_FRAME_BLANKING_LINES
uint16_t output_height
Output height.
#define MT9F002_LINE_LENGTH_MAX
uint16_t op_sys_clk_div
Fixed PLL config from calculator tool.
struct img_size_t output_size
Output image size.
uint8_t rowSpeed_2_0
Fixed PLL config from calculator tool.
#define MT9F002_OUTPUT_HEIGHT
uint16_t vt_pix_clk_div
Fixed PLL config from calculator tool.
#define MT9F002_DAC_LD_14_15
uint16_t pll_multiplier
Fixed PLL config from calculator tool.
#define MT9F002_SCALING_MODE
static void mt9f002_mipi_stage1(struct mt9f002_t *mt)
Configure stage 1 for both MiPi and HiSPi connection.
#define MT9F002_BLUE_GAIN
#define MT9F002_X_ODD_INC
float set_offset_x
Signed fractional offset from centre of image of original sensor [-0.5,0.5].
#define MT9F002_TARGET_EXPOSURE
Exposure of the front camera of the bebop.
float set_offset_y
Signed fractional offset from centre of image of original sensor [-0.5,0.5].
#define MT9F002_COARSE_INTEGRATION_TIME_MIN
#define MT9F002_DIGITAL_TEST
#define MT9F002_ANALOG_CONTROL4
#define MT9F002_DAC_LD_28_29
static uint32_t read_reg(struct mt9f002_t *mt, uint16_t addr, uint8_t len)
Read multiple bytes from a register.
float gain_blue
Gain for the Blue pixels [1., 63.50].
#define MT9F002_READ_MODE
#define MT9F002_CTX_CONTROL_REG
#define MT9F002_VT_PIX_CLK_DIV
uint16_t offset_x
Offset from left in pixels.
static void mt9f002_set_resolution(struct mt9f002_t *mt)
uint8_t y_odd_inc
Y increment for subsampling (1,3,7,15,31 accepted)
uint16_t vt_sys_clk_div
Fixed PLL config from calculator tool.
#define MT9F002_OP_SYS_CLK_DIV
#define MT9F002_DAC_LD_24_25
#define MT9F002_SERIAL_FORMAT
bool i2c_blocking_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction and wait for it to complete.
uint16_t output_scaler
Output scaler.
#define MT9F002_DATA_PEDESTAL_
#define MT9F002_ANALOG_CONTROL5
void mt9f002_init(struct mt9f002_t *mt)
Initialisation of the Aptina MT9F002 CMOS sensor (front camera)
uint16_t fine_integration_time_max_margin
#define MT9F002_Y_OUTPUT_SIZE
uint8_t shift_vt_pix_clk_div
Fixed PLL config from calculator tool.
#define MT9F002_COARSE_INTEGRATION_TIME
uint8_t row_speed_10_8
Fixed PLL config from calculator tool.
void mt9f002_setting_update_color(float in)
transaction set to done by user level
#define VERBOSE_PRINT(...)
enum mt9f002_interface interface
Interface used to connect.
#define MT9F002_GREEN1_GAIN
static void mt9f002_mipi_stage3(struct mt9f002_t *mt)
Configure stage 3 for both MiPi and HiSPi connection.
static uint16_t mt9f002_calc_gain(float gain)
Calculate the gain based on value of 1.0 -> 63.50.
uint16_t line_length
Calculated line length of blanking.
uint16_t min_line_length_pck
float real_fps
Real calculated FPS.
#define MT9F002_GAIN_BLUE
#define MT9F002_DATAPATH_SELECT
#define MT9F002_RESET_REGISTER
static void mt9f002_parallel_stage1(struct mt9f002_t *mt)
Configure stage 1 for parallel connection.
static void mt9f002_set_pll(struct mt9f002_t *mt)
Set the PLL registers based on config.
#define CFG_MT9F002_X_ADDR_MIN
float gain_green1
Gain for the GreenR pixels [1., 63.50].
#define MT9F002_ANALOG_CONTROL7
uint16_t output_width
Output width.
#define MT9F002_FRAME_LENGTH_LINES
static void write_reg(struct mt9f002_t *mt, uint16_t addr, uint32_t val, uint8_t len)
Write multiple bytes to a single register.
void mt9f002_set_gains(struct mt9f002_t *mt)
Sets the GreenR, Blue, Red and GreenB gains.
float vt_pix_clk
Calculated based on PLL.
float target_fps
FPS wanted.
#define MT9F002_X_OUTPUT_SIZE
#define MT9F002_COLUMN_CORRECTION
#define MT9F002_DARK_CONTROL3
#define MT9F002_Y_ADDR_END
#define MT9F002_EXTRA_DELAY
float gain_red
Gain for the Red pixels [1., 63.50].
#define MT9F002_OUTPUT_WIDTH
enum I2CTransactionStatus status
Transaction status.
#define MT9F002_GAIN_GREEN1
#define MT9F002_COARSE_INTEGRATION_TIME_MAX_MARGIN
struct i2c_periph * i2c_periph
I2C peripheral used to communicate over.
float gain_green2
Gain for the GreenB pixels [1., 63.50].
#define MT9F002_VT_SYS_CLK_DIV
Initialization and configuration of the MT9F002 CMOS Chip.
#define MT9F002_MODE_SELECT
uint16_t offset_y
Offset from top in pixels.
#define MT9F002_OP_PIX_CLK_DIV
float real_exposure
Real exposure time in ms.
#define MT9F002_GREEN2_GAIN
#define MT9F002_SMIA_TEST
struct i2c_transaction i2c_trans
I2C transaction for communication with CMOS chip.
#define PRINT(string,...)
#define MT9F002_GLOBAL_GAIN
uint16_t min_line_fifo_pck
#define VIDEO_FILTER_ISP
Enable ISP.
#define MT9F002_Y_ADDR_START
int isp_request_statistics_yuv_window(uint16_t x_start, uint16_t x_end, uint16_t y_start, uint16_t y_end, uint16_t x_odd_inc, uint16_t y_odd_inc)
#define CFG_MT9F002_WINDOW_HEIGHT_MIN
#define MT9F002_CPP_DATA_FORMAT
uint16_t op_pix_clk_div
Fixed PLL config from calculator tool.
#define CFG_MT9F002_PIXEL_ARRAY_WIDTH
#define CFG_MT9F002_WINDOW_WIDTH_MIN
#define CFG_MT9F002_Y_ADDR_MAX
#define MT9F002_PLL_MULTIPLIER
void mt9f002_reset_exposure(struct mt9f002_t *mt)
void mt9f002_setting_update_resolution(float in)
float op_pix_clk
Calculated based on PLL.
#define MT9F002_Y_ODD_INC
uint16_t pre_pll_clk_div
Fixed PLL config from calculator tool.
Parallel type connection.
static void mt9f002_set_blanking(struct mt9f002_t *mt)
#define MT9F002_FRAME_LENGTH_MAX
void mt9f002_reset_color(struct mt9f002_t *mt)
uint32_t int32_gcd(uint32_t a, uint32_t b)
#define MT9F002_TARGET_FPS
#define CFG_MT9F002_PIXEL_ARRAY_HEIGHT
static void mt9f002_mipi_stage2(struct mt9f002_t *mt)
Configure stage 2 for both MiPi and HiSPi connection.
#define MT9F002_PRE_PLL_CLK_DIV
static void mt9f002_calc_resolution(struct mt9f002_t *mt)
#define MT9F002_X_ADDR_START
#define MT9F002_ROW_SPEED
uint16_t frame_length
Calculated frame length of blanking.
float input_clk_freq
Input clock frequency.
#define MT9F002_GAIN_GREEN2
float target_exposure
Target exposure time in ms.
bool i2c_blocking_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction and wait for it to complete.
Paparazzi fixed point algebra.
struct video_config_t front_camera