Skip to content
114 changes: 89 additions & 25 deletions source/application/lua_libraries/camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ static struct camera_auto_last_values
double green_gain;
double blue_gain;
} last = {
.shutter = 500.0f,
.shutter = 4096.0f,
.analog_gain = 1.0f,
.red_gain = 1.9f,
.green_gain = 1.0f,
.blue_gain = 2.2f,
.red_gain = 121.6f,
.green_gain = 64.0f,
.blue_gain = 140.8f,
};

static struct camera_capture_settings
Expand Down Expand Up @@ -561,11 +561,12 @@ static int lua_camera_auto(lua_State *L)
}

// Default auto exposure settings
camera_metering_mode_t metering = AVERAGE;
double target_exposure = 0.18;
double exposure_speed = 0.50;
double shutter_limit = 1600.0;
double analog_gain_limit = 60.0;
camera_metering_mode_t metering = CENTER_WEIGHTED;
double target_exposure = 0.1;
double exposure_speed = 0.45;
double shutter_limit = 16383.0;
double analog_gain_limit = 16.0;
double rgb_gain_limit = 287.0;

// Default white balance settings
double white_balance_speed = 0.5;
Expand Down Expand Up @@ -655,6 +656,17 @@ static int lua_camera_auto(lua_State *L)

lua_pop(L, 1);
}

if (lua_getfield(L, 1, "rgb_gain_limit") != LUA_TNIL)
{
rgb_gain_limit = luaL_checknumber(L, -1);
if (rgb_gain_limit < 0.0 || rgb_gain_limit > 1023.0)
{
luaL_error(L, "rgb_gain_limit must be between 0 and 1023");
}

lua_pop(L, 1);
}
}

// Get current brightness from FPGA
Expand All @@ -668,6 +680,25 @@ static int lua_camera_auto(lua_State *L)
double matrix_g = metering_data[4] / 255.0f;
double matrix_b = metering_data[5] / 255.0f;

if (spot_r == 0.0) {
spot_r = 0.0001;
}
if (spot_g == 0.0) {
spot_g = 0.0001;
}
if (spot_b == 0.0) {
spot_b = 0.0001;
}
if (matrix_r == 0.0) {
matrix_r = 0.0001;
}
if (matrix_g == 0.0) {
matrix_g = 0.0001;
}
if (matrix_b == 0.0) {
matrix_b = 0.0001;
}

double spot_average = (spot_r + spot_g + spot_b) / 3.0;
double matrix_average = (matrix_r + matrix_g + matrix_b) / 3.0;
double center_weighted_average = (spot_average +
Expand Down Expand Up @@ -769,6 +800,10 @@ static int lua_camera_auto(lua_State *L)
? matrix_g / last.green_gain
: matrix_b / last.blue_gain);

// scale normalized RGB values to the gain scale
max_rgb *= 256.0;

// target per-channel gains that we blend towards
double red_gain = max_rgb / matrix_r * last.red_gain;
double green_gain = max_rgb / matrix_g * last.green_gain;
double blue_gain = max_rgb / matrix_b * last.blue_gain;
Expand All @@ -777,19 +812,6 @@ static int lua_camera_auto(lua_State *L)
double blending_factor = (scene_brightness - white_balance_min_activation) /
(white_balance_max_activation -
white_balance_min_activation);

if (red_gain > 1023.0)
{
red_gain = 1023.0;
}
if (green_gain > 1023.0)
{
green_gain = 1023.0;
}
if (blue_gain > 1023.0)
{
blue_gain = 1023.0;
}
if (blending_factor > 1.0)
{
blending_factor = 1.0;
Expand All @@ -811,9 +833,51 @@ static int lua_camera_auto(lua_State *L)
(blue_gain - last.blue_gain) +
last.blue_gain;

uint16_t red_gain_uint16 = (uint16_t)(last.red_gain * 256.0);
uint16_t green_gain_uint16 = (uint16_t)(last.green_gain * 256.0);
uint16_t blue_gain_uint16 = (uint16_t)(last.blue_gain * 256.0);
double max_rgb_gain = last.red_gain > last.green_gain
? (last.red_gain > last.blue_gain
? last.red_gain
: last.blue_gain)
: (last.green_gain > last.blue_gain
? last.green_gain
: last.blue_gain);

// Scale per-channel gains so the largest channel is at most rgb_gain_limit
if (max_rgb_gain > rgb_gain_limit)
{
double scale_factor = rgb_gain_limit / max_rgb_gain;
last.red_gain *= scale_factor;
last.green_gain *= scale_factor;
last.blue_gain *= scale_factor;
}

if (last.red_gain > 1023.0)
{
last.red_gain = 1023.0;
}
if (last.red_gain <= 0.0)
{
last.red_gain = 0.0001;
}
if (last.green_gain > 1023.0)
{
last.green_gain = 1023.0;
}
if (last.green_gain <= 0.0)
{
last.green_gain = 0.0001;
}
if (last.blue_gain > 1023.0)
{
last.blue_gain = 1023.0;
}
if (last.blue_gain <= 0.0)
{
last.blue_gain = 0.0001;
}

uint16_t red_gain_uint16 = (uint16_t)(last.red_gain);
uint16_t green_gain_uint16 = (uint16_t)(last.green_gain);
uint16_t blue_gain_uint16 = (uint16_t)(last.blue_gain);

check_error(i2c_write(CAMERA, 0x5180, 0x03, red_gain_uint16 >> 8).fail);
check_error(i2c_write(CAMERA, 0x5181, 0xFF, red_gain_uint16).fail);
Expand Down