pkarashchenko commented on code in PR #6280: URL: https://github.com/apache/incubator-nuttx/pull/6280#discussion_r875642213
########## drivers/video/isx019.c: ########## @@ -0,0 +1,3247 @@ +/**************************************************************************** + * drivers/video/isx019.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <sys/time.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <debug.h> +#include <nuttx/i2c/i2c_master.h> +#include <nuttx/signal.h> +#include <arch/board/board.h> +#include <nuttx/video/isx019.h> +#include <nuttx/video/imgsensor.h> +#include <math.h> +#include <nuttx/semaphore.h> + +#include "isx019_reg.h" +#include "isx019_range.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Wait time on power on sequence. */ + +#define TRANSITION_TIME_TO_STARTUP (120 * 1000) /* unit : usec */ +#define TRANSITION_TIME_TO_STREAMING (30 * 1000) /* unit : usec */ + +/* For get_supported_value() I/F */ + +#define SET_RANGE(range, min, max, s, def) \ + do \ + { \ + range.minimum = min; \ + range.maximum = max; \ + range.step = s; \ + range.default_value = def; \ + } \ + while (0); + +#define SET_DISCRETE(disc, nr, val, def) \ + do \ + { \ + disc.nr_values = nr; \ + disc.values = val; \ + disc.default_value = def; \ + } \ + while (0); + +#define SET_ELEMS(elem, nr, min, max, s) \ + do \ + { \ + elem.nr_elems = nr; \ + elem.minimum = min; \ + elem.maximum = max; \ + elem.step = s; \ + } \ + while (0); + +#define COMPARE_FRAMESIZE(w, h, sup_w, sup_h) (((w) == (sup_w)) && \ + ((h) == (sup_h))) + +#define VALIDATE_FRAMESIZE(w, h) (COMPARE_FRAMESIZE((w), (h), 1280, 960) || \ + COMPARE_FRAMESIZE((w), (h), 1280, 720) || \ + COMPARE_FRAMESIZE((w), (h), 640, 480) || \ + COMPARE_FRAMESIZE((w), (h), 640, 360) || \ + COMPARE_FRAMESIZE((w), (h), 480, 360) || \ + COMPARE_FRAMESIZE((w), (h), 320, 240) || \ + COMPARE_FRAMESIZE((w), (h), 160, 120)) + +#define VALIDATE_THUMNAIL_SIZE(m, s) (((s) != 0) && \ + ((m) % (s) == 0) && \ + ((m) / (s) < 5) && \ + ((m) / (s) > 0)) + +/* For set_value() and get_value() I/F */ + +#define SET_REGINFO(a, c, o, s) do \ + { \ + (a)->category = (c); \ + (a)->offset = (o); \ + (a)->size = (s); \ + } \ + while (0); + +#define VALIDATE_RANGE(v, min, max, step) (((v) >= (min)) && \ + ((v) <= (max)) && \ + (((v) - (min)) % (step) == 0)) + +/* Offset for IMGSENSOR_ID_3A_PARAMETER control */ + +#define OFFSET_3APARAMETER_AWB_R (0) +#define OFFSET_3APARAMETER_AWB_B (2) +#define OFFSET_3APARAMETER_AE_SHTTIME (4) +#define OFFSET_3APARAMETER_AE_GAIN (8) + +/* Index of array for drive mode setting */ + +#define INDEX_SENS (0) +#define INDEX_POST (1) +#define INDEX_SENSPOST (2) +#define INDEX_IO (3) + +/* Timer value for power on control */ + +#define ISX019_ACCESSIBLE_WAIT_SEC (0) +#define ISX019_ACCESSIBLE_WAIT_USEC (200000) +#define FPGA_ACCESSIBLE_WAIT_SEC (1) +#define FPGA_ACCESSIBLE_WAIT_USEC (0) + +/* Array size of DQT setting for JPEG quality */ + +#define JPEG_DQT_ARRAY_SIZE (64) + +/* ISX019 standard master clock */ + +#define ISX019_STANDARD_MASTER_CLOCK (27000000) + +/* Vivid colors setting */ + +#define VIVID_COLORS_SATURATION (0xf0) +#define VIVID_COLORS_SHARPNESS (0x20) + +/* Black white colors setting */ + +#define BW_COLORS_SATURATION (0x00) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct isx019_default_value_s +{ + int32_t brightness; + int32_t contrast; + int32_t saturation; + int32_t hue; + int32_t awb; + int32_t gamma; + int32_t ev; + int32_t hflip_video; + int32_t vflip_video; + int32_t hflip_still; + int32_t vflip_still; + int32_t sharpness; + int32_t ae; + int32_t exptime; + int32_t wbmode; + int32_t hdr; + int32_t iso; + int32_t iso_auto; + int32_t meter; + int32_t threealock; + int32_t threeastatus; + int32_t jpgquality; +}; + +typedef struct isx019_default_value_s isx019_default_value_t; + +struct isx019_rect_s +{ + int32_t left; + int32_t top; + uint32_t width; + uint32_t height; +}; + +typedef struct isx019_rect_s isx019_rect_t; + +struct isx019_dev_s +{ + sem_t fpga_lock; + sem_t i2c_lock; + FAR struct i2c_master_s *i2c; + float clock_ratio; + isx019_default_value_t default_value; + imgsensor_stream_type_t stream; + imgsensor_white_balance_t wb_mode; + uint8_t flip_video; + uint8_t flip_still; + isx019_rect_t clip_video; + isx019_rect_t clip_still; + int32_t iso; + double gamma; + int32_t jpg_quality; + imgsensor_colorfx_t colorfx; +}; + +typedef struct isx019_dev_s isx019_dev_t; + +typedef int32_t (*convert_t)(int32_t value32); + +typedef int (*setvalue_t)(imgsensor_value_t value); +typedef int (*getvalue_t)(imgsensor_value_t *value); + +struct isx019_reginfo_s +{ + uint16_t category; + uint16_t offset; + uint8_t size; +}; + +typedef struct isx019_reginfo_s isx019_reginfo_t; + +struct isx019_fpga_jpg_quality_s +{ + /* JPEG quality */ + + int quality; + + /* DQT header setting for y component */ + + uint8_t y_head[JPEG_DQT_ARRAY_SIZE]; + + /* DQT calculation data for y component */ + + uint8_t y_calc[JPEG_DQT_ARRAY_SIZE]; + + /* DQT header setting for c component */ + + uint8_t c_head[JPEG_DQT_ARRAY_SIZE]; + + /* DQT calculation data for c component */ + + uint8_t c_calc[JPEG_DQT_ARRAY_SIZE]; +}; + +typedef struct isx019_fpga_jpg_quality_s isx019_fpga_jpg_quality_t; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static bool isx019_is_available(void); +static int isx019_init(void); +static int isx019_uninit(void); +static const char *isx019_get_driver_name(void); +static int isx019_validate_frame_setting(imgsensor_stream_type_t type, + uint8_t nr_datafmt, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); +static int isx019_start_capture(imgsensor_stream_type_t type, + uint8_t nr_datafmt, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); +static int isx019_stop_capture(imgsensor_stream_type_t type); +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, FAR imgsensor_value_t *value); +static int isx019_set_value + (uint32_t id, uint32_t size, imgsensor_value_t value); +static int initialize_jpg_quality(void); +static int send_read_cmd(struct i2c_config_s *config, + uint8_t cat, + uint16_t addr, + uint8_t size); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static isx019_dev_t g_isx019_private; + +static struct imgsensor_ops_s g_isx019_ops = +{ + isx019_is_available, + isx019_init, + isx019_uninit, + isx019_get_driver_name, + isx019_validate_frame_setting, + isx019_start_capture, + isx019_stop_capture, + isx019_get_supported_value, + isx019_get_value, + isx019_set_value, +}; + +static isx019_fpga_jpg_quality_t g_isx019_jpg_quality[] = +{ + { + 10, + { + 21, 15, 15, 26, 18, 26, 43, 21, + 21, 43, 43, 43, 32, 43, 43, 43, + 43, 43, 43, 43, 43, 64, 43, 43, + 43, 43, 43, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 3, 4, 133, 131, 131, 131, 1, 1, + 4, 135, 3, 131, 131, 131, 1, 1, + 133, 3, 2, 131, 131, 1, 1, 1, + 131, 131, 131, 131, 1, 1, 1, 1, + 131, 131, 131, 1, 1, 1, 1, 1, + 131, 131, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + }, + { + 21, 26, 26, 32, 26, 32, 43, 26, + 26, 43, 64, 43, 32, 43, 64, 64, + 64, 43, 43, 64, 64, 64, 64, 64, + 43, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 3, 133, 2, 131, 1, 1, 1, 1, + 133, 133, 133, 131, 1, 1, 1, 1, + 2, 133, 2, 131, 1, 1, 1, 1, + 131, 131, 131, 131, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + } + }, + { + 20, + { + 18, 14, 14, 14, 15, 14, 21, 15, + 15, 21, 32, 21, 18, 21, 32, 32, + 26, 21, 21, 26, 32, 32, 26, 26, + 26, 26, 26, 32, 43, 32, 32, 32, + 32, 32, 32, 43, 43, 43, 43, 43, + 43, 43, 43, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 135, 137, 137, 3, 2, 2, 2, 131, + 137, 4, 4, 3, 133, 133, 2, 131, + 137, 4, 135, 3, 133, 2, 131, 1, + 3, 3, 3, 133, 2, 131, 1, 1, + 2, 133, 133, 2, 131, 1, 1, 1, + 2, 133, 2, 131, 1, 1, 1, 1, + 2, 2, 131, 1, 1, 1, 1, 1, + 131, 131, 1, 1, 1, 1, 1, 1, + }, + { + 21, 21, 21, 21, 26, 21, 26, 21, + 21, 26, 26, 21, 26, 21, 26, 32, + 26, 26, 26, 26, 32, 43, 32, 32, + 32, 32, 32, 43, 64, 43, 43, 43, + 43, 43, 43, 64, 64, 64, 43, 43, + 43, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 3, 3, 3, 133, 133, 2, 131, 1, + 3, 133, 3, 3, 133, 2, 131, 1, + 3, 3, 133, 133, 2, 131, 1, 1, + 133, 3, 133, 2, 131, 131, 1, 1, + 133, 133, 2, 131, 131, 1, 1, 1, + 2, 2, 131, 131, 1, 1, 1, 1, + 131, 131, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + } + }, + { + 30, + { + 15, 11, 11, 11, 12, 11, 15, 12, + 12, 15, 21, 15, 13, 15, 21, 26, + 21, 15, 15, 21, 26, 32, 21, 21, + 21, 21, 21, 32, 32, 21, 26, 26, + 26, 26, 21, 32, 32, 32, 32, 43, + 32, 32, 32, 43, 43, 43, 43, 43, + 43, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 4, 12, 12, 4, 3, 133, 2, 2, + 12, 139, 139, 4, 3, 3, 3, 2, + 12, 139, 5, 4, 3, 133, 2, 131, + 4, 4, 4, 3, 133, 2, 131, 1, + 3, 3, 3, 133, 131, 131, 1, 1, + 133, 3, 133, 2, 131, 1, 1, 1, + 2, 3, 2, 131, 1, 1, 1, 1, + 2, 2, 131, 1, 1, 1, 1, 1, + }, + { + 18, 15, 15, 18, 18, 18, 21, 18, + 18, 21, 21, 18, 21, 18, 21, 26, + 21, 21, 21, 21, 26, 43, 26, 26, + 26, 26, 26, 43, 43, 32, 32, 32, + 32, 32, 32, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 135, 4, 135, 3, 3, 133, 131, 131, + 4, 135, 135, 135, 3, 133, 2, 131, + 135, 135, 3, 3, 133, 2, 131, 131, + 3, 135, 3, 133, 2, 131, 131, 1, + 3, 3, 133, 2, 131, 131, 1, 1, + 133, 133, 2, 131, 131, 1, 1, 1, + 131, 2, 131, 131, 1, 1, 1, 1, + 131, 131, 131, 1, 1, 1, 1, 1, + } + }, + { + 40, + { + 12, 8, 8, 8, 9, 8, 12, 9, + 9, 12, 18, 11, 10, 11, 18, 21, + 15, 12, 12, 15, 21, 26, 18, 18, + 21, 18, 18, 26, 21, 18, 21, 21, + 21, 21, 18, 21, 21, 26, 26, 32, + 26, 26, 21, 32, 32, 43, 43, 32, + 32, 43, 43, 43, 43, 43, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 139, 8, 8, 139, 135, 3, 133, 3, + 8, 7, 7, 12, 4, 135, 135, 3, + 8, 7, 141, 139, 135, 3, 133, 2, + 139, 12, 139, 3, 3, 133, 2, 131, + 135, 4, 135, 3, 2, 131, 131, 1, + 3, 135, 3, 133, 131, 131, 1, 1, + 133, 135, 133, 2, 131, 1, 1, 1, + 3, 3, 2, 131, 1, 1, 1, 1, + }, + { + 13, 11, 11, 13, 14, 13, 15, 14, + 14, 15, 21, 14, 15, 14, 21, 21, + 15, 18, 18, 15, 21, 26, 21, 21, + 21, 21, 21, 26, 32, 26, 21, 21, + 21, 21, 26, 32, 32, 32, 32, 32, + 32, 32, 32, 43, 43, 32, 32, 43, + 43, 43, 43, 43, 43, 43, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }, + { + 5, 12, 5, 4, 3, 3, 133, 2, + 12, 137, 137, 137, 4, 3, 133, 2, + 5, 137, 4, 135, 3, 3, 2, 131, + 4, 137, 135, 3, 3, 2, 131, 131, + 3, 4, 3, 3, 2, 2, 131, 1, + 3, 3, 3, 2, 2, 131, 1, 1, + 133, 133, 2, 131, 131, 1, 1, 1, + 2, 2, 131, 131, 1, 1, 1, 1, + } + }, + { + 50, + { + 8, 6, 6, 6, 6, 6, 8, 6, + 6, 8, 12, 8, 7, 8, 12, 14, + 10, 8, 8, 10, 14, 15, 13, 13, + 14, 13, 13, 15, 18, 12, 14, 13, + 13, 14, 12, 18, 15, 18, 18, 21, + 18, 18, 15, 26, 26, 26, 26, 26, + 26, 32, 32, 32, 32, 32, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + }, + { + 8, 11, 11, 8, 139, 137, 4, 135, + 11, 11, 11, 8, 141, 5, 139, 4, + 11, 11, 9, 8, 5, 137, 135, 133, + 8, 8, 8, 137, 5, 135, 133, 2, + 139, 141, 5, 5, 3, 133, 2, 131, + 137, 5, 137, 135, 133, 2, 131, 131, + 4, 139, 135, 133, 2, 131, 131, 131, + 135, 4, 133, 2, 131, 131, 131, 131, + }, + { + 9, 8, 8, 9, 10, 9, 11, 9, + 9, 11, 14, 11, 13, 11, 14, 18, + 14, 14, 14, 14, 18, 18, 13, 13, + 14, 13, 13, 18, 26, 18, 15, 15, + 15, 15, 18, 26, 21, 21, 21, 21, + 21, 21, 21, 26, 26, 26, 26, 26, + 26, 32, 32, 32, 32, 32, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + }, + { + 7, 8, 7, 12, 137, 135, 135, 133, + 8, 141, 7, 12, 137, 5, 135, 3, + 7, 7, 5, 137, 5, 4, 3, 133, + 12, 12, 137, 137, 4, 3, 133, 2, + 137, 137, 5, 4, 3, 133, 2, 131, + 135, 5, 4, 3, 133, 2, 131, 131, + 135, 135, 3, 133, 2, 131, 131, 131, + 133, 3, 133, 2, 131, 131, 131, 131, + } + }, + { + 60, + { + 6, 4, 4, 4, 5, 4, 6, 5, + 5, 6, 9, 6, 5, 6, 9, 11, + 8, 6, 6, 8, 11, 12, 10, 10, + 11, 10, 10, 12, 15, 12, 12, 12, + 12, 12, 12, 15, 12, 14, 15, 15, + 15, 14, 12, 18, 18, 21, 21, 18, + 18, 26, 26, 26, 26, 26, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + }, + { + 11, 16, 16, 11, 7, 12, 139, 4, + 16, 13, 13, 11, 8, 141, 139, 139, + 16, 13, 13, 11, 141, 139, 137, 135, + 11, 11, 11, 12, 139, 4, 135, 133, + 7, 8, 141, 139, 4, 3, 133, 2, + 12, 141, 139, 4, 3, 133, 2, 2, + 139, 139, 137, 135, 133, 2, 2, 2, + 4, 139, 135, 133, 2, 2, 2, 2, + }, + { + 7, 7, 7, 13, 12, 13, 26, 15, + 15, 26, 26, 21, 18, 21, 26, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + }, + { + 9, 9, 5, 133, 133, 2, 2, 2, + 9, 139, 4, 3, 2, 2, 2, 2, + 5, 4, 135, 2, 2, 2, 2, 2, + 133, 3, 2, 2, 2, 2, 2, 2, + 133, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + } + }, + { + 70, + { + 4, 3, 3, 3, 3, 3, 4, 3, + 3, 4, 6, 4, 3, 4, 6, 7, + 5, 4, 4, 5, 7, 8, 6, 6, + 7, 6, 6, 8, 10, 8, 9, 9, + 9, 9, 8, 10, 10, 12, 12, 12, + 12, 12, 10, 12, 12, 13, 13, 12, + 12, 18, 18, 18, 18, 18, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + }, + { + 16, 21, 21, 16, 11, 9, 8, 141, + 21, 21, 21, 16, 13, 11, 8, 141, + 21, 21, 21, 16, 11, 7, 139, 139, + 16, 16, 16, 9, 7, 139, 139, 135, + 11, 13, 11, 7, 139, 5, 135, 3, + 9, 11, 7, 139, 5, 135, 3, 3, + 8, 8, 139, 139, 135, 3, 3, 3, + 141, 141, 139, 135, 3, 3, 3, 3, + }, + { + 4, 5, 5, 8, 7, 8, 15, 10, + 10, 15, 21, 14, 14, 14, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + }, + { + 16, 13, 8, 4, 3, 3, 3, 3, + 13, 9, 141, 137, 3, 3, 3, 3, + 8, 141, 137, 3, 3, 3, 3, 3, + 4, 137, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + } + }, + { + 80, + { + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 2, 2, 2, 3, 4, + 3, 2, 2, 3, 4, 5, 4, 4, + 4, 4, 4, 5, 6, 5, 5, 5, + 5, 5, 5, 6, 6, 7, 7, 8, + 7, 7, 6, 9, 9, 10, 10, 9, + 9, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + }, + { + 32, 32, 32, 32, 21, 16, 13, 11, + 32, 32, 32, 32, 21, 16, 13, 11, + 32, 32, 32, 32, 16, 13, 9, 7, + 32, 32, 32, 16, 13, 9, 7, 139, + 21, 21, 16, 13, 8, 141, 139, 139, + 16, 16, 13, 9, 141, 139, 139, 139, + 13, 13, 9, 7, 139, 139, 139, 139, + 11, 11, 7, 139, 139, 139, 139, 139, + }, + { + 3, 3, 3, 5, 4, 5, 9, 6, + 6, 9, 13, 11, 9, 11, 13, 15, + 14, 14, 14, 14, 15, 15, 12, 12, + 12, 12, 12, 15, 15, 12, 12, 12, + 12, 12, 12, 15, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + }, + { + 21, 21, 13, 7, 5, 4, 4, 4, + 21, 16, 11, 12, 137, 139, 139, 139, + 13, 11, 7, 137, 139, 139, 139, 139, + 7, 12, 137, 139, 139, 139, 139, 139, + 5, 137, 139, 139, 139, 139, 139, 139, + 4, 139, 139, 139, 139, 139, 139, 139, + 4, 139, 139, 139, 139, 139, 139, 139, + 4, 139, 139, 139, 139, 139, 139, 139, + } + }, + { + 90, + { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 2, 2, + 2, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 3, 2, 3, 3, + 3, 3, 2, 3, 3, 4, 4, 4, + 4, 4, 3, 5, 5, 5, 5, 5, + 5, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + }, + { + 64, 64, 64, 64, 32, 32, 32, 21, + 64, 64, 64, 64, 32, 32, 32, 21, + 64, 64, 64, 64, 32, 21, 16, 13, + 64, 64, 64, 32, 21, 16, 13, 9, + 32, 32, 32, 21, 16, 13, 9, 8, + 32, 32, 21, 16, 13, 9, 8, 8, + 32, 32, 16, 13, 9, 8, 8, 8, + 21, 21, 13, 9, 8, 8, 8, 8, + }, + { + 1, 1, 1, 2, 2, 2, 5, 3, + 3, 5, 7, 5, 4, 5, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + }, + { + 64, 64, 32, 13, 9, 8, 8, 8, + 64, 32, 21, 13, 8, 8, 8, 8, + 32, 21, 16, 8, 8, 8, 8, 8, + 13, 13, 8, 8, 8, 8, 8, 8, + 9, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + } + }, + { + 100, + { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + }, + { + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 32, + 64, 64, 64, 64, 64, 64, 32, 32, + 64, 64, 64, 64, 64, 32, 32, 21, + 64, 64, 64, 64, 32, 32, 21, 21, + 64, 64, 64, 32, 32, 21, 21, 21, + 64, 64, 32, 32, 21, 21, 21, 21, + }, + { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, 2, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + }, + { + 64, 64, 64, 64, 32, 21, 21, 21, + 64, 64, 64, 32, 21, 21, 21, 21, + 64, 64, 64, 21, 21, 21, 21, 21, + 64, 32, 21, 21, 21, 21, 21, 21, + 32, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + } + } +}; + +#define NR_JPGSETTING_TBL \ + (sizeof(g_isx019_jpg_quality) / sizeof(isx019_fpga_jpg_quality_t)) + +int32_t g_isx019_colorfx[] = +{ + IMGSENSOR_COLORFX_NONE, + IMGSENSOR_COLORFX_BW, + IMGSENSOR_COLORFX_VIVID, +}; + +#define NR_COLORFX (sizeof(g_isx019_colorfx) / sizeof(int32_t)) + +int32_t g_isx019_wbmode[] = +{ + IMGSENSOR_WHITE_BALANCE_AUTO, + IMGSENSOR_WHITE_BALANCE_INCANDESCENT, + IMGSENSOR_WHITE_BALANCE_FLUORESCENT, + IMGSENSOR_WHITE_BALANCE_DAYLIGHT, + IMGSENSOR_WHITE_BALANCE_CLOUDY, + IMGSENSOR_WHITE_BALANCE_SHADE, +}; + +#define NR_WBMODE (sizeof(g_isx019_wbmode) / sizeof(int32_t)) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void i2c_lock(void) +{ + nxsem_wait_uninterruptible(&g_isx019_private.i2c_lock); +} + +static void i2c_unlock(void) +{ + nxsem_post(&g_isx019_private.i2c_lock); +} + +static void fpga_lock(void) +{ + nxsem_wait_uninterruptible(&g_isx019_private.fpga_lock); +} + +static void fpga_unlock(void) +{ + nxsem_post(&g_isx019_private.fpga_lock); +} + +static int fpga_i2c_write(uint8_t addr, uint8_t *data, uint8_t size) +{ + struct i2c_config_s config; + static uint8_t buf[FPGA_I2C_REGSIZE_MAX + FPGA_I2C_REGADDR_LEN]; + int ret; + + DEBUGASSERT(size <= FPGA_I2C_REGSIZE_MAX); + + config.frequency = ISX019_I2C_FREQUENCY; + config.address = ISX019_I2C_SLVADDR; + config.addrlen = ISX019_I2C_SLVADDR_LEN; + + i2c_lock(); + + /* ISX019 requires that send read command to ISX019 before FPGA access. */ + + send_read_cmd(&config, CAT_VERSION, ROM_VERSION, 1); + + config.frequency = FPGA_I2C_FREQUENCY; + config.address = FPGA_I2C_SLVADDR; + config.addrlen = FPGA_I2C_SLVADDR_LEN; + + buf[FPGA_I2C_OFFSET_ADDR] = addr; + memcpy(&buf[FPGA_I2C_OFFSET_WRITEDATA], data, size); + ret = i2c_write(g_isx019_private.i2c, + &config, + buf, + size + FPGA_I2C_REGADDR_LEN); + i2c_unlock(); + + return ret; +} + +static int fpga_i2c_read(uint8_t addr, uint8_t *data, uint8_t size) +{ + int ret; + struct i2c_config_s config; + + DEBUGASSERT(size <= FPGA_I2C_REGSIZE_MAX); + + config.frequency = ISX019_I2C_FREQUENCY; + config.address = ISX019_I2C_SLVADDR; + config.addrlen = ISX019_I2C_SLVADDR_LEN; + + i2c_lock(); + + /* ISX019 requires that send read command to ISX019 before FPGA access. */ + + send_read_cmd(&config, CAT_VERSION, ROM_VERSION, 1); + + config.frequency = FPGA_I2C_FREQUENCY; + config.address = FPGA_I2C_SLVADDR; + config.addrlen = FPGA_I2C_SLVADDR_LEN; + + ret = i2c_write(g_isx019_private.i2c, + &config, + &addr, + FPGA_I2C_REGADDR_LEN); + if (ret >= 0) + { + ret = i2c_read(g_isx019_private.i2c, &config, data, size); + } + + i2c_unlock(); + + return ret; +} + +static void fpga_activate_setting(void) +{ + uint8_t regval = FPGA_ACTIVATE_REQUEST; + fpga_i2c_write(FPGA_ACTIVATE, ®val, 1); + + while (1) + { + fpga_i2c_read(FPGA_ACTIVATE, ®val, 1); + if (regval == 0) + { + break; + } + } +} + +static uint8_t calc_isx019_chksum(uint8_t *data, uint8_t len) +{ + int i; + uint8_t chksum = 0; + + for (i = 0; i < len; i++) + { + /* ISX019 checksum is lower 8bit of addition result. + * So, no problem even if overflow occur. + */ + + chksum += data[i]; + } + + return chksum; +} + +static bool validate_isx019_chksum(uint8_t *data, uint8_t len) +{ + uint8_t chksum; + + chksum = calc_isx019_chksum(data, len - 1); + + return (data[len - 1] == chksum) ? true : false; +} + +static int recv_write_response(struct i2c_config_s *config) +{ + int ret; + uint8_t buf[ISX019_I2C_WRRES_TOTALLEN]; + + ret = i2c_read(g_isx019_private.i2c, config, buf, sizeof(buf)); + if (ret < 0) + { + return ret; + } + + if ((buf[ISX019_I2C_OFFSET_TOTALLEN] != ISX019_I2C_WRRES_TOTALLEN) || + (buf[ISX019_I2C_OFFSET_CMDNUM] != 1) || + (buf[ISX019_I2C_OFFSET_CMDLEN] != ISX019_I2C_WRRES_LEN) || + (buf[ISX019_I2C_OFFSET_STS] != ISX019_I2C_STS_OK) || + !validate_isx019_chksum(buf, ISX019_I2C_WRRES_TOTALLEN)) + { + return -EPROTO; + } + + return OK; +} + +static int recv_read_response(struct i2c_config_s *config, + uint8_t *data, + uint8_t size) +{ + int ret; + uint8_t buf[ISX019_I2C_WRREQ_TOTALLEN(ISX019_I2C_REGSIZE_MAX)] = + { + 0 + }; + + DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX); + + ret = i2c_read(g_isx019_private.i2c, + config, buf, ISX019_I2C_RDRES_TOTALLEN(size)); + if (ret < 0) + { + return ret; + } + + if ((buf[ISX019_I2C_OFFSET_TOTALLEN] != ISX019_I2C_RDRES_TOTALLEN(size)) || + (buf[ISX019_I2C_OFFSET_CMDNUM] != 1) || + (buf[ISX019_I2C_OFFSET_CMDLEN] != ISX019_I2C_RDRES_LEN(size)) || + (buf[ISX019_I2C_OFFSET_STS] != ISX019_I2C_STS_OK) || + !validate_isx019_chksum(buf, ISX019_I2C_RDRES_TOTALLEN(size))) + { + return -EPROTO; + } + + memcpy(data, &buf[ISX019_I2C_OFFSET_READDATA], size); + + return OK; +} + +static int send_write_cmd(struct i2c_config_s *config, + uint8_t cat, + uint16_t addr, + uint8_t *data, + uint8_t size) +{ + int len; + uint8_t buf[ISX019_I2C_WRREQ_TOTALLEN(ISX019_I2C_REGSIZE_MAX)] = + { + 0 + }; + + DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX); + + buf[ISX019_I2C_OFFSET_TOTALLEN] = ISX019_I2C_WRREQ_TOTALLEN(size); + buf[ISX019_I2C_OFFSET_CMDNUM] = 1; + buf[ISX019_I2C_OFFSET_CMDLEN] = ISX019_I2C_WRREQ_LEN(size); + buf[ISX019_I2C_OFFSET_CMD] = ISX019_I2C_CMD_WRITE; + buf[ISX019_I2C_OFFSET_CATEGORY] = cat; + buf[ISX019_I2C_OFFSET_ADDRESS_H] = addr >> 8; + buf[ISX019_I2C_OFFSET_ADDRESS_L] = addr & 0xff; + + memcpy(&buf[ISX019_I2C_OFFSET_WRITEDATA], data, size); + + len = ISX019_I2C_OFFSET_WRITEDATA + size; + buf[len] = calc_isx019_chksum(buf, len); + len++; + + return i2c_write(g_isx019_private.i2c, config, buf, len); +} + +static int isx019_i2c_write(uint8_t cat, + uint16_t addr, + uint8_t *data, + uint8_t size) +{ + int ret; + struct i2c_config_s config; + + DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX); + + config.frequency = ISX019_I2C_FREQUENCY; + config.address = ISX019_I2C_SLVADDR; + config.addrlen = ISX019_I2C_SLVADDR_LEN; + + i2c_lock(); + + ret = send_write_cmd(&config, cat, addr, data, size); + if (ret == OK) + { + ret = recv_write_response(&config); + } + + i2c_unlock(); + return ret; +} + +static int send_read_cmd(struct i2c_config_s *config, + uint8_t cat, + uint16_t addr, + uint8_t size) +{ + int ret; + int len; + uint8_t buf[ISX019_I2C_RDREQ_TOTALLEN] = + { + 0 + }; + + buf[ISX019_I2C_OFFSET_TOTALLEN] = ISX019_I2C_RDREQ_TOTALLEN; + buf[ISX019_I2C_OFFSET_CMDNUM] = 1; + buf[ISX019_I2C_OFFSET_CMDLEN] = ISX019_I2C_RDREQ_LEN; + buf[ISX019_I2C_OFFSET_CMD] = ISX019_I2C_CMD_READ; + buf[ISX019_I2C_OFFSET_CATEGORY] = cat; + buf[ISX019_I2C_OFFSET_ADDRESS_H] = addr >> 8; + buf[ISX019_I2C_OFFSET_ADDRESS_L] = addr & 0xff; + buf[ISX019_I2C_OFFSET_READSIZE] = size; + + len = ISX019_I2C_OFFSET_READSIZE + 1; + buf[len] = calc_isx019_chksum(buf, len); + len++; + + ret = i2c_write(g_isx019_private.i2c, config, buf, len); + return ret; +} + +static int isx019_i2c_read(uint8_t cat, + uint16_t addr, + uint8_t *data, + uint8_t size) +{ + int ret; + struct i2c_config_s config; + + DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX); + + config.frequency = ISX019_I2C_FREQUENCY; + config.address = ISX019_I2C_SLVADDR; + config.addrlen = ISX019_I2C_SLVADDR_LEN; + + i2c_lock(); + + ret = send_read_cmd(&config, cat, addr, size); + if (ret == OK) + { + ret = recv_read_response(&config, data, size); + } + + i2c_unlock(); + + return ret; +} + +static void fpga_init(void) +{ + uint8_t regval; + + regval = FPGA_RESET_ENABLE; + fpga_i2c_write(FPGA_RESET, ®val, 1); + regval = FPGA_DATA_OUTPUT_STOP; + fpga_i2c_write(FPGA_DATA_OUTPUT, ®val, 1); + fpga_activate_setting(); + regval = FPGA_RESET_RELEASE; + fpga_i2c_write(FPGA_RESET, ®val, 1); + fpga_activate_setting(); +} + +static int set_drive_mode(void) +{ + uint8_t drv[] = + { +#ifdef CONFIG_VIDEO_ISX019_DOL2 + DOL2_30FPS_SENS, DOL2_30FPS_POST, DOL2_30FPS_SENSPOST, DOL2_30FPS_IO +#else + DOL3_30FPS_SENS, DOL3_30FPS_POST, DOL3_30FPS_SENSPOST, DOL3_30FPS_IO +#endif + }; + + nxsig_usleep(TRANSITION_TIME_TO_STARTUP); + + isx019_i2c_write(CAT_CONFIG, MODE_SENSSEL, &drv[INDEX_SENS], 1); + isx019_i2c_write(CAT_CONFIG, MODE_POSTSEL, &drv[INDEX_POST], 1); + isx019_i2c_write(CAT_CONFIG, MODE_SENSPOST_SEL, &drv[INDEX_SENSPOST], 1); + + nxsig_usleep(TRANSITION_TIME_TO_STREAMING); + + return OK; +} + +static bool try_repeat(int sec, int usec, int (* trial_func)(void)) +{ + int ret; + struct timeval start; + struct timeval now; + struct timeval delta; + struct timeval wait; + + wait.tv_sec = sec; + wait.tv_usec = usec; + + gettimeofday(&start, NULL); + while (1) + { + ret = trial_func(); + if (ret != -ENODEV) + { + break; + } + else + { + gettimeofday(&now, NULL); + timersub(&now, &start, &delta); + if (timercmp(&delta, &wait, >)) Review Comment: I think that ESP32 build on MAC issue was resolved yesterday. Please rebase and check. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org