Compare commits

...

5 Commits

Author SHA1 Message Date
dchvs c2113b443d Fix low framerate 2021-03-08 16:29:16 -06:00
dchvs ca8e71f447 Add script to control AE on sensor-id=0 2021-03-08 16:29:16 -06:00
dchvs 7f1843d73d Fix gain equation on Driver 2021-03-08 16:29:16 -06:00
dchvs fef47412d5 documentation: Update README with AE 2021-03-08 16:29:16 -06:00
dchvs cccd9ac76c Fix gain & exposure range on DTB 2021-03-08 16:29:16 -06:00
4 changed files with 163 additions and 78 deletions

View File

@ -33,7 +33,7 @@ gst-launch-1.0 nvarguscamerasrc sensor-id=0 aelock=true awblock=true ! 'video/x-
### UDP Streaming Test ### UDP Streaming Test
#### Sender Endpoint #### Sender Endpoint
``` ```
gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)30/1' ! omxh264enc control-rate=2 bitrate=8000000 ! 'video/x-h264, stream-format=(string)byte-stream' ! h264parse ! rtph264pay mtu=1400 ! udpsink host=$HOST_IP port=5000 sync=false async=false gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)60/1' ! omxh264enc control-rate=2 bitrate=8000000 ! 'video/x-h264, stream-format=(string)byte-stream' ! h264parse ! rtph264pay mtu=1400 ! udpsink host=$HOST_IP port=5000 sync=false async=false
``` ```
#### Receiver Endpoint #### Receiver Endpoint
@ -71,11 +71,58 @@ v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=RG12 -
#### Slave #### Slave
``` ```
v4l2-ctl -d /dev/video01 --set-fmt-video=width=1280,height=720,pixelformat=RG12 --set-ctrl bypass_mode=0 --stream-mmap v4l2-ctl -d /dev/video1 --set-fmt-video=width=1280,height=720,pixelformat=RG12 --set-ctrl bypass_mode=0 --stream-mmap
```
### AE Synchronized
First run the master pipeline and then the slave pipeline:
#### Master Pipeline
```
gst-launch-1.0 nvarguscamerasrc sensor-id=1 ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)60/1' ! fakesink
```
#### Slave Pipeline
```
gst-launch-1.0 nvarguscamerasrc sensor-id=0 aelock=true awblock=true ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)60/1' ! fakesink
```
### Run script
```
./script_to_control_gain_exposure.sh &
``` ```
## Appends ## Appends
#### Auto Exposure
The AE controls realays in the feedback provided by the Driver's camera sensor to the nvarguscamerasrc libraries,
and the custom DTSIs with the sensor parameters definitions.
As the AE has interdependency with the digital gain. This gain it's and operation on the Driver, and follows this setup:
```bash
/*
* Digital gain equation:
*
* RANGE: 1x, 7.97x
* GAIN: VAL / STEPS;
* STEPS: 1/32
*
* SCALE FACTOR = 100.000
*
* min_gain_val = 100.000
* max_gain_val = 797.000
* step_gain_val = 3125
*/
MT9M021 sensor datasheet:
* <a href="https://files.niemo.de/aptina_pdfs/MT9M021-M031_Developer_Guide.pdf">MT9M021 Developer Guide</a>
```
Where, the min_gain_val, max_gain_val, step_gain_val are part of the cameras' DTSI (tegra186-tx2-spiri-camera.dtsi) fixed parameters
as per the datasheet. The step_gain_val consists of the steps (1/32 for the register) scaled to a value that makes this fraction become an significant
in integer.
#### Kernel Changes #### Kernel Changes
The Driver for the MT9M021 cameras consists on the following structure, that adds the DTB and Kernel sources, along with its Makefiles that lead its portability to a Kernel source. The Driver for the MT9M021 cameras consists on the following structure, that adds the DTB and Kernel sources, along with its Makefiles that lead its portability to a Kernel source.

View File

@ -98,26 +98,25 @@ i2c8 = "/i2c@31e0000";
inherent_gain = "1"; inherent_gain = "1";
pix_clk_hz = "74250000"; pix_clk_hz = "74250000";
gain_factor = "1"; gain_factor = "3125";
framerate_factor = "1000000"; framerate_factor = "1000000";
exposure_factor = "1000000"; exposure_factor = "1000000";
min_gain_val = "4"; min_gain_val = "100000";
max_gain_val = "6476"; max_gain_val = "796000";
step_gain_val = "1"; step_gain_val = "1";
default_gain = "100"; default_gain = "100000";
min_hdr_ratio = "1"; min_hdr_ratio = "1";
max_hdr_ratio = "1"; max_hdr_ratio = "1";
min_framerate = "2000000"; min_framerate = "2000000";
max_framerate = "60000000"; max_framerate = "60000000";
step_framerate = "1"; step_framerate = "1";
default_framerate = "6000000"; // 60.0 fps default_framerate = "60000000"; // 60.0 fps
min_exp_time = "23"; // us min_exp_time = "500"; // us
max_exp_time = "14933"; // us max_exp_time = "16000"; // us
step_exp_time = "1"; step_exp_time = "1";
default_exp_time = "10000"; // us default_exp_time = "12000"; // us
}; };
ports { ports {
#address-cells = <0x1>; #address-cells = <0x1>;
@ -186,25 +185,25 @@ i2c8 = "/i2c@31e0000";
inherent_gain = "1"; inherent_gain = "1";
pix_clk_hz = "74250000"; pix_clk_hz = "74250000";
gain_factor = "1"; gain_factor = "3125";
framerate_factor = "1000000"; framerate_factor = "1000000";
exposure_factor = "1000000"; exposure_factor = "1000000";
min_gain_val = "4"; min_gain_val = "100000";
max_gain_val = "6476"; max_gain_val = "796000";
step_gain_val = "1"; step_gain_val = "1";
default_gain = "100"; default_gain = "100000";
min_hdr_ratio = "1"; min_hdr_ratio = "1";
max_hdr_ratio = "1"; max_hdr_ratio = "1";
min_framerate = "2000000"; min_framerate = "2000000";
max_framerate = "60000000"; max_framerate = "60000000";
step_framerate = "1"; step_framerate = "1";
default_framerate = "6000000"; // 60.0 fps default_framerate = "60000000"; // 60.0 fps
min_exp_time = "23"; // us min_exp_time = "500"; // us
max_exp_time = "14933"; // us max_exp_time = "16000"; // us
step_exp_time = "1"; step_exp_time = "1";
default_exp_time = "10000"; // us default_exp_time = "12000"; // us
}; };
ports { ports {
#address-cells = <0x1>; #address-cells = <0x1>;

View File

@ -135,8 +135,8 @@
#define MT9M021_ANALOG_GAIN_SHIFT 4 #define MT9M021_ANALOG_GAIN_SHIFT 4
#define MT9M021_ANALOG_GAIN_MASK 0x0030 #define MT9M021_ANALOG_GAIN_MASK 0x0030
#define MT9M021_GLOBAL_GAIN_MIN 4 #define MT9M021_GLOBAL_GAIN_MIN 100000
#define MT9M021_GLOBAL_GAIN_MAX 6476 #define MT9M021_GLOBAL_GAIN_MAX 796000
#define MT9M021_GLOBAL_GAIN_DEF 100 #define MT9M021_GLOBAL_GAIN_DEF 100
#define MT9M021_COARSE_INT_TIME_MIN 0x0001 #define MT9M021_COARSE_INT_TIME_MIN 0x0001
@ -396,54 +396,61 @@ static int mt9m021_set_gain(struct tegracam_device *tc_dev, s64 val)
{ {
struct camera_common_data *s_data = tc_dev->s_data; struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev; struct device *dev = tc_dev->dev;
int err = 0; int err = 0;
u16 gain_mul; u16 gain_mul;
u16 reg16 = 0; u16 reg16 = 0;
u8 integer, fraction; u64 gain = 0;
dev_dbg(dev, "Setting Gain to: %lld", val); dev_dbg(dev, "Setting Gain to: %lld", val);
if (val >= MT9M021_GAIN_8X_FIXED) { if (val >= MT9M021_GAIN_8X_FIXED) {
integer = val / MT9M021_GAIN_8X_FIXED; gain_mul = MT9M021_GAIN_8X;
fraction = ((val / 8) % 100) * 32 / 100; } else if (val >= MT9M021_GAIN_4X_FIXED) {
gain_mul = MT9M021_GAIN_8X; gain_mul = MT9M021_GAIN_4X;
} else if (val >= MT9M021_GAIN_4X_FIXED) { } else if (val >= MT9M021_GAIN_2X_FIXED) {
integer = val / MT9M021_GAIN_4X_FIXED; gain_mul = MT9M021_GAIN_2X;
fraction = ((val / 4) % 100) * 32 / 100; } else {
gain_mul = MT9M021_GAIN_4X; gain_mul = MT9M021_GAIN_1X;
} else if (val >= MT9M021_GAIN_2X_FIXED) { }
integer = val / MT9M021_GAIN_2X_FIXED;
fraction = ((val / 2) % 100) * 32 / 100;
gain_mul = MT9M021_GAIN_2X;
} else {
integer = val / MT9M021_GAIN_1X_FIXED;
fraction = (val % 100) * 32 / 100;
gain_mul = MT9M021_GAIN_1X;
}
/* Update analog gain multiplier */ /*
err = mt9m021_read_reg16(s_data, MT9M021_DIGITAL_TEST, &reg16); * Digital gain equation:
if (err) *
goto exit; * RANGE: 1x, 7.97x
reg16 = * GAIN: VAL / STEPS;
(reg16 & ~MT9M021_ANALOG_GAIN_MASK) | * STEPS: 1/32
((gain_mul << MT9M021_ANALOG_GAIN_SHIFT) & *
MT9M021_ANALOG_GAIN_MASK); * SCALE FACTOR = 100.000
err = mt9m021_write_reg16(s_data, MT9M021_DIGITAL_TEST, reg16); *
msleep(10); * min_gain_val = 100.000
if (err) * max_gain_val = 797.000
goto exit; * gain_factor = 3125
*
* gain maps to range 32 - 255
*/
gain = val / 3125;
/* Update analog gain multiplier */
err = mt9m021_read_reg16(s_data, MT9M021_DIGITAL_TEST, &reg16);
if (err)
goto exit;
reg16 =
(reg16 & ~MT9M021_ANALOG_GAIN_MASK) |
((gain_mul << MT9M021_ANALOG_GAIN_SHIFT) &
MT9M021_ANALOG_GAIN_MASK);
err = mt9m021_write_reg16(s_data, MT9M021_DIGITAL_TEST, reg16);
// msleep(10);
if (err)
goto exit;
/* Update global gain */ /* Update global gain */
err = err =
mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN, mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN, gain);
(integer << 5) | fraction); // msleep(10);
msleep(10);
if (err) if (err)
goto exit; goto exit;
err = err =
mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN_CB, mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN_CB, gain);
(integer << 5) | fraction);
if (err) if (err)
goto exit; goto exit;
@ -485,8 +492,8 @@ static int mt9m021_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
/* Calculate frame-length */ /* Calculate frame-length */
frame_length = mode->signal_properties.pixel_clock.val * frame_length = mode->signal_properties.pixel_clock.val *
mode->control_properties.framerate_factor / mode->control_properties.framerate_factor /
mode->image_properties.line_length / val; mode->image_properties.line_length / val;
err = mt9m021_set_frame_length(priv, frame_length); err = mt9m021_set_frame_length(priv, frame_length);
if (err) if (err)
@ -507,13 +514,13 @@ static int mt9m021_set_coarse_time(struct mt9m021 *priv, s64 val)
dev_dbg(dev, "Setting Coarse Time to: %lld", val); dev_dbg(dev, "Setting Coarse Time to: %lld", val);
err = mt9m021_write_reg16(s_data, MT9M021_COARSE_INT_TIME, val); err = mt9m021_write_reg16(s_data, MT9M021_COARSE_INT_TIME, val);
if (err) if (err)
return err; return err;
err = mt9m021_write_reg16(s_data, MT9M021_COARSE_INT_TIME_CB, val); err = mt9m021_write_reg16(s_data, MT9M021_COARSE_INT_TIME_CB, val);
if (err) if (err)
return err; return err;
msleep(30); // msleep(30);
return 0; return 0;
} }
@ -524,18 +531,18 @@ static int mt9m021_set_exposure(struct tegracam_device *tc_dev, s64 val)
struct mt9m021 *priv = (struct mt9m021 *)tc_dev->priv; struct mt9m021 *priv = (struct mt9m021 *)tc_dev->priv;
struct device *dev = tc_dev->dev; struct device *dev = tc_dev->dev;
const struct sensor_mode_properties *mode = const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode]; &s_data->sensor_props.sensor_modes[s_data->mode];
u64 coarse_time; u64 coarse_time;
int err = 0; int err = 0;
dev_dbg(dev, "Setting Exposure Time to: %lld", val); dev_dbg(dev, "Setting Exposure Time to : %lld", val);
/* Calculate coarse-time */ coarse_time =
coarse_time = mode->signal_properties.pixel_clock.val * val * mode->signal_properties.pixel_clock.val /
val / mode->image_properties.line_length / mode->image_properties.line_length /
mode->control_properties.exposure_factor; mode->control_properties.exposure_factor;
err = mt9m021_set_coarse_time(priv, coarse_time); err = mt9m021_set_coarse_time(priv, coarse_time);
if (err) if (err)
goto exit; goto exit;
@ -564,7 +571,7 @@ static int mt9m021_set_analog_gain(struct tegracam_device *tc_dev, s64 val)
((val << MT9M021_ANALOG_GAIN_SHIFT) & ((val << MT9M021_ANALOG_GAIN_SHIFT) &
MT9M021_ANALOG_GAIN_MASK); MT9M021_ANALOG_GAIN_MASK);
err = mt9m021_write_reg16(s_data, MT9M021_DIGITAL_TEST, reg16); err = mt9m021_write_reg16(s_data, MT9M021_DIGITAL_TEST, reg16);
msleep(30); // msleep(30);
if (err) if (err)
goto exit; goto exit;
@ -620,7 +627,7 @@ static int mt9m021_set_digital_gain(struct tegracam_device *tc_dev, s64 val,
err = mt9m021_write_reg16(s_data, gain_cb_reg, val); err = mt9m021_write_reg16(s_data, gain_cb_reg, val);
if (err) if (err)
goto exit; goto exit;
msleep(30); // msleep(30);
return 0; return 0;
@ -643,7 +650,7 @@ static int mt9m021_set_test_pattern(struct tegracam_device *tc_dev, s32 val)
else else
err = mt9m021_write_reg16(s_data, MT9M021_TEST_PATTERN, err = mt9m021_write_reg16(s_data, MT9M021_TEST_PATTERN,
val); val);
msleep(30); // msleep(30);
if (err) if (err)
goto exit; goto exit;
@ -956,13 +963,15 @@ static int mt9m021_col_correction(struct mt9m021 *priv)
if (ret < 0) if (ret < 0)
return ret; return ret;
msleep(200); // msleep(200);
// usleep(200);
/* Enable Streaming */ /* Enable Streaming */
ret = mt9m021_write_table(priv, mode_table[MT9M021_MODE_START_STREAM]); ret = mt9m021_write_table(priv, mode_table[MT9M021_MODE_START_STREAM]);
if (ret < 0) if (ret < 0)
return ret; return ret;
msleep(200); // msleep(200);
// usleep(200);
/* Disable Streaming */ /* Disable Streaming */
ret = mt9m021_write_table(priv, mode_table[MT9M021_MODE_STOP_STREAM]); ret = mt9m021_write_table(priv, mode_table[MT9M021_MODE_STOP_STREAM]);
@ -973,7 +982,8 @@ static int mt9m021_col_correction(struct mt9m021 *priv)
ret = mt9m021_write_reg16(s_data, MT9M021_COLUMN_CORRECTION, 0xE007); ret = mt9m021_write_reg16(s_data, MT9M021_COLUMN_CORRECTION, 0xE007);
if (ret < 0) if (ret < 0)
return ret; return ret;
msleep(200); // msleep(200);
// usleep(200);
return ret; return ret;
} }
@ -1003,7 +1013,7 @@ static int mt9m021_set_mode(struct tegracam_device *tc_dev)
dev_err(dev, "%s: Failed to set pll setup\n", __func__); dev_err(dev, "%s: Failed to set pll setup\n", __func__);
return ret; return ret;
} }
msleep(100); msleep(100);
ret = mt9m021_col_correction(priv); ret = mt9m021_col_correction(priv);
if (ret < 0) { if (ret < 0) {
@ -1088,7 +1098,7 @@ static int mt9m021_get_trigger_mode(struct mt9m021 *priv)
} }
err = err =
of_property_read_string(node, "trigger_mode", &priv->trigger_mode); of_property_read_string(node, "trigger_mode", &priv->trigger_mode);
if (err == -EINVAL) { if (err == -EINVAL) {
dev_warn(&client->dev, "trigger_mode not in device tree\n"); dev_warn(&client->dev, "trigger_mode not in device tree\n");
*(&priv->trigger_mode) = "master"; *(&priv->trigger_mode) = "master";

View File

@ -0,0 +1,29 @@
#!/bin/bash
initial_gain=0
initial_exposure_time=0
while true; do sleep 0.5;
# Read center camera controls
echo `v4l2-ctl -d /dev/video1 --get-ctrl=gain --get-ctrl=exposure` > controls
awk '{print $2}' controls > get_control
actual_gain=`cat get_control`
awk '{print $4}' controls > get_control
actual_exposure_time=`cat get_control`
# Print controls
#echo -e "\n**Center Camera Controls**"
#cat controls
# Remove temp files
rm controls get_control
# Set R/L camera controls manually
if [ $actual_gain -ne $initial_gain ]; then
v4l2-ctl -d /dev/video0 --set-ctrl=gain=$actual_gain
fi
if [ $actual_exposure_time -ne $initial_exposure_time ]; then
v4l2-ctl -d /dev/video0 --set-ctrl=exposure=$actual_exposure_time
fi
# Define new initial value
initial_gain=$actual_gain
initial_exposure_time=$actual_exposure_time
done