diff --git a/drivers/video/isx012.c b/drivers/video/isx012.c index f05f28e1fd..8564df7703 100644 --- a/drivers/video/isx012.c +++ b/drivers/video/isx012.c @@ -628,6 +628,7 @@ static struct imgsensor_ops_s g_isx012_ops = isx012_validate_frame_setting, /* validate_frame_setting */ isx012_start_capture, /* start_capture */ isx012_stop_capture, /* stop_capture */ + NULL, /* get_frame_interval */ isx012_get_supported_value, /* get_supported_value */ isx012_get_value, /* get_value */ isx012_set_value /* set_value */ diff --git a/drivers/video/isx019.c b/drivers/video/isx019.c index f4d4c53bd2..7ef9e15393 100644 --- a/drivers/video/isx019.c +++ b/drivers/video/isx019.c @@ -148,6 +148,11 @@ #define BW_COLORS_SATURATION (0x00) +/* Definition for calculation of extended frame number */ + +#define VTIME_PER_FRAME (30518) +#define INTERVAL_PER_FRAME (33333) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -267,6 +272,8 @@ static int isx019_start_capture(imgsensor_stream_type_t type, FAR imgsensor_format_t *datafmts, FAR imgsensor_interval_t *interval); static int isx019_stop_capture(imgsensor_stream_type_t type); +static int isx019_get_frame_interval(imgsensor_stream_type_t type, + FAR imgsensor_interval_t *interval); static int isx019_get_supported_value(uint32_t id, FAR imgsensor_supported_value_t *value); static int isx019_get_value(uint32_t id, uint32_t size, @@ -294,6 +301,7 @@ static struct imgsensor_ops_s g_isx019_ops = isx019_validate_frame_setting, isx019_start_capture, isx019_stop_capture, + isx019_get_frame_interval, isx019_get_supported_value, isx019_get_value, isx019_set_value, @@ -1607,6 +1615,86 @@ static int isx019_stop_capture(imgsensor_stream_type_t type) return OK; } +static int calc_gcm(int a, int b) +{ + int r; + + DEBUGASSERT((a != 0) && (b != 0)); + + while ((r = a % b) != 0) + { + a = b; + b = r; + } + + return b; +} + +static int isx019_get_frame_interval(imgsensor_stream_type_t type, + FAR imgsensor_interval_t *interval) +{ + uint32_t vtime = VTIME_PER_FRAME; + uint32_t frame = 1; + uint8_t fps = FPGA_FPS_1_1; + int decimation = 1; + int gcm; + + if (interval == NULL) + { + return -EINVAL; + } + + /* ISX019's base frame interval = 1/30. */ + + interval->denominator = 30; + interval->numerator = 1; + + /* ISX019 has the frame extension feature, which automatically + * exposes longer than one frame in dark environment. + * The number of extended frame is calculated from V_TIME register, + * which has the value + * VTIME_PER_FRAME + INTERVAL_PER_FRAME * (frame number - 1) + */ + + isx019_i2c_read(CAT_AESOUT, V_TIME, (FAR uint8_t *)&vtime, 4); + frame = 1 + (vtime - VTIME_PER_FRAME) / INTERVAL_PER_FRAME; + interval->numerator *= frame; + + /* Also, consider frame decimation by FPGA. + * decimation amount is gotten from FPGA register. + */ + + fpga_i2c_read(FPGA_FPS_AND_THUMBNAIL, &fps, 1); + switch (fps & FPGA_FPS_BITS) + { + case FPGA_FPS_1_1: + decimation = 1; + break; + + case FPGA_FPS_1_2: + decimation = 2; + break; + + case FPGA_FPS_1_3: + decimation = 3; + break; + + default: /* FPGA_FPS_1_4 */ + decimation = 4; + break; + } + + interval->numerator *= decimation; + + /* Reduce the fraction. */ + + gcm = calc_gcm(30, frame * decimation); + interval->denominator /= gcm; + interval->numerator /= gcm; + + return OK; +} + static int isx019_get_supported_value(uint32_t id, FAR imgsensor_supported_value_t *val) { diff --git a/drivers/video/video.c b/drivers/video/video.c index f82992c6e4..b7c5d03793 100644 --- a/drivers/video/video.c +++ b/drivers/video/video.c @@ -1630,6 +1630,46 @@ static int video_s_parm(FAR struct video_mng_s *priv, return ret; } +static int video_g_parm(FAR struct video_mng_s *vmng, + FAR struct v4l2_streamparm *parm) +{ + int ret = -EINVAL; + FAR video_type_inf_t *type_inf; + + DEBUGASSERT(vmng && g_video_sensor_ops); + + type_inf = get_video_type_inf(vmng, parm->type); + if (type_inf == NULL) + { + return -EINVAL; + } + + if ((type_inf->state == VIDEO_STATE_CAPTURE) && + (g_video_sensor_ops->get_frame_interval != NULL)) + { + /* If capture is started and lower driver has the get_frame_interval(), + * query lower driver. + */ + + memset(&parm->parm, 0, sizeof(parm->parm)); + + ret = g_video_sensor_ops->get_frame_interval + (parm->type, + (imgsensor_interval_t *)&parm->parm.capture.timeperframe); + } + + if (ret != OK) + { + /* In no capture state or error case, return stored value. */ + + memcpy(&parm->parm.capture.timeperframe, + &type_inf->frame_interval, + sizeof(struct v4l2_fract)); + } + + return OK; +} + static int video_streamon(FAR struct video_mng_s *vmng, FAR enum v4l2_buf_type *type) { @@ -2955,6 +2995,11 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; + case VIDIOC_G_PARM: + ret = video_g_parm(priv, (FAR struct v4l2_streamparm *)arg); + + break; + case VIDIOC_QUERYCTRL: ret = video_queryctrl((FAR struct v4l2_queryctrl *)arg); diff --git a/include/nuttx/video/imgsensor.h b/include/nuttx/video/imgsensor.h index d40aa080f5..f31eb3b55f 100644 --- a/include/nuttx/video/imgsensor.h +++ b/include/nuttx/video/imgsensor.h @@ -333,7 +333,8 @@ struct imgsensor_ops_s FAR imgsensor_format_t *datafmts, FAR imgsensor_interval_t *interval); CODE int (*stop_capture)(imgsensor_stream_type_t type); - + CODE int (*get_frame_interval)(imgsensor_stream_type_t type, + FAR imgsensor_interval_t *interval); CODE int (*get_supported_value)(uint32_t id, FAR imgsensor_supported_value_t *value); CODE int (*get_value)(uint32_t id, diff --git a/include/nuttx/video/video.h b/include/nuttx/video/video.h index bf35e88d9e..b7703e7749 100644 --- a/include/nuttx/video/video.h +++ b/include/nuttx/video/video.h @@ -190,6 +190,12 @@ extern "C" #define VIDIOC_G_SELECTION _VIDIOC(0x001d) +/* Get the frame interval. + * Address pointing to struct v4l2_streamparm + */ + +#define VIDIOC_G_PARM _VIDIOC(0x001e) + #define VIDEO_HSIZE_QVGA (320) /* QVGA horizontal size */ #define VIDEO_VSIZE_QVGA (240) /* QVGA vertical size */ #define VIDEO_HSIZE_VGA (640) /* VGA horizontal size */