Update FLIR Lepton driver.

* Fix window code.
* Support smaller resolutions.
This commit is contained in:
Kwabena W. Agyeman 2018-05-26 17:36:00 -07:00 committed by iabdalkader
parent 7d16d008f9
commit 804d97f5b0
2 changed files with 195 additions and 117 deletions

View File

@ -141,6 +141,7 @@ static int reset(sensor_t *sensor)
} }
LEP_AGC_ROI_T roi; LEP_AGC_ROI_T roi;
if (LEP_GetAgcROI(&tmp_handle, &roi) != LEP_OK) { if (LEP_GetAgcROI(&tmp_handle, &roi) != LEP_OK) {
return -1; return -1;
} }
@ -151,6 +152,7 @@ static int reset(sensor_t *sensor)
if (LEP_SetAgcEnableState(&tmp_handle, LEP_AGC_ENABLE) != LEP_OK) { if (LEP_SetAgcEnableState(&tmp_handle, LEP_AGC_ENABLE) != LEP_OK) {
return -1; return -1;
} }
if (LEP_SetAgcCalcEnableState(&tmp_handle, LEP_AGC_ENABLE) != LEP_OK) { if (LEP_SetAgcCalcEnableState(&tmp_handle, LEP_AGC_ENABLE) != LEP_OK) {
return -1; return -1;
} }
@ -287,6 +289,8 @@ static int set_lens_correction(sensor_t *sensor, int enable, int radi, int coef)
static int snapshot(sensor_t *sensor, image_t *image) static int snapshot(sensor_t *sensor, image_t *image)
{ {
fb_update_jpeg_buffer();
if ((!h_res) || (!v_res) || (!sensor->framesize) || (!sensor->pixformat)) { if ((!h_res) || (!v_res) || (!sensor->framesize) || (!sensor->pixformat)) {
return -1; return -1;
} }
@ -361,57 +365,57 @@ static int snapshot(sensor_t *sensor, image_t *image)
} }
} }
//image_t img; image_t img;
//img.w = sensor->fb_w; img.w = MAIN_FB()->u;
//img.h = sensor->fb_h; img.h = MAIN_FB()->v;
//img.bpp = MAIN_FB()->bpp; // invalid img.bpp = MAIN_FB()->bpp; // invalid
//img.data = MAIN_FB()->pixels; // valid img.data = MAIN_FB()->pixels; // valid
//float x_scale = resolution[sensor->framesize][0] / ((float) h_res); float x_scale = resolution[sensor->framesize][0] / ((float) h_res);
//float y_scale = resolution[sensor->framesize][1] / ((float) v_res); float y_scale = resolution[sensor->framesize][1] / ((float) v_res);
// MAX == KeepAspectRationByExpanding - MIN == KeepAspectRatio // MAX == KeepAspectRationByExpanding - MIN == KeepAspectRatio
//float scale = IM_MAX(x_scale, y_scale); float scale = IM_MAX(x_scale, y_scale);
//int x_offset = (resolution[sensor->framesize][0] - (h_res * scale)) / 2; int x_offset = (resolution[sensor->framesize][0] - (h_res * scale)) / 2;
//int y_offset = (resolution[sensor->framesize][1] - (v_res * scale)) / 2; int y_offset = (resolution[sensor->framesize][1] - (v_res * scale)) / 2;
//// The code below upscales the source image to the requested frame size // The code below upscales the source image to the requested frame size
//// and then crops it to the window set by the user. // and then crops it to the window set by the user.
//for (int yyy = fast_floorf(y * scale) + y_offset, for (int yyy = fast_floorf(y * scale) + y_offset,
// yyyy = fast_ceilf((y + 1) * scale) + y_offset; yyy < yyyy; yyy++) { yyyy = fast_ceilf((y + 1) * scale) + y_offset; yyy < yyyy; yyy++) {
// if ((sensor->fb_y <= yyy) && (yyy < (sensor->fb_y + sensor->fb_h))) { if ((MAIN_FB()->y <= yyy) && (yyy < (MAIN_FB()->y + MAIN_FB()->v))) {
// for (int xxx = fast_floorf(x * scale) + x_offset, for (int xxx = fast_floorf(x * scale) + x_offset,
// xxxx = fast_ceilf((x + VOSPI_LINE_PIXELS) * scale) + x_offset; xxx < xxxx; xxx++) { xxxx = fast_ceilf((x + VOSPI_LINE_PIXELS) * scale) + x_offset; xxx < xxxx; xxx++) {
// if ((sensor->fb_x <= xxx) && (xxx < (sensor->fb_x + sensor->fb_w))) { if ((MAIN_FB()->x <= xxx) && (xxx < (MAIN_FB()->x + MAIN_FB()->u))) {
// int i = (xxx / scale) - x; int i = (xxx / scale) - x;
// // Value is the 14-bit value from the FLIR IR camera. // Value is the 14-bit value from the FLIR IR camera.
// // However, with AGC enabled only the bottom 8-bits are non-zero. // However, with AGC enabled only the bottom 8-bits are non-zero.
// int value = ((buffer[(i*2)+4] << 8) | (buffer[(i*2)+5] << 0)) & 0x3FFF; int value = ((buffer[(i*2)+4] << 8) | (buffer[(i*2)+5] << 0)) & 0x3FFF;
// int t_x = xxx - sensor->fb_x; int t_x = xxx - MAIN_FB()->x;
// int t_y = yyy - sensor->fb_y; int t_y = yyy - MAIN_FB()->y;
// if (h_mirror) t_x = sensor->fb_w - t_x - 1; if (h_mirror) t_x = MAIN_FB()->u - t_x - 1;
// if (v_flip) t_y = sensor->fb_h - t_y - 1; if (v_flip) t_y = MAIN_FB()->v - t_y - 1;
// switch (sensor->pixformat) { switch (sensor->pixformat) {
// case PIXFORMAT_RGB565: { case PIXFORMAT_RGB565: {
// IMAGE_PUT_RGB565_PIXEL(&img, t_x, t_y, rainbow_table[value & 0xFF]); IMAGE_PUT_RGB565_PIXEL(&img, t_x, t_y, rainbow_table[value & 0xFF]);
// break; break;
// } }
// case PIXFORMAT_GRAYSCALE: { case PIXFORMAT_GRAYSCALE: {
// IMAGE_PUT_GRAYSCALE_PIXEL(&img, t_x, t_y, value & 0xFF); IMAGE_PUT_GRAYSCALE_PIXEL(&img, t_x, t_y, value & 0xFF);
// break; break;
// } }
// default: { default: {
// break; break;
// } }
// } }
// } }
// } }
// } }
//} }
x += VOSPI_LINE_PIXELS; x += VOSPI_LINE_PIXELS;
} }
@ -424,6 +428,28 @@ static int snapshot(sensor_t *sensor, image_t *image)
} }
} }
MAIN_FB()->w = MAIN_FB()->u;
MAIN_FB()->h = MAIN_FB()->v;
switch (sensor->pixformat) {
case PIXFORMAT_RGB565: {
MAIN_FB()->bpp = sizeof(uint16_t);
break;
}
case PIXFORMAT_GRAYSCALE: {
MAIN_FB()->bpp = sizeof(uint8_t);
break;
}
default: {
break;
}
}
image->w = MAIN_FB()->w;
image->h = MAIN_FB()->h;
image->bpp = MAIN_FB()->bpp;
image->data = MAIN_FB()->pixels;
return 0; return 0;
} }

View File

@ -6,17 +6,16 @@
* MT9V034 driver. * MT9V034 driver.
* *
*/ */
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include STM32_HAL_H #include STM32_HAL_H
#include "cambus.h" #include "cambus.h"
#include "sensor.h" #include "mt9v034.h"
#include "systick.h" #include "systick.h"
#include "framebuffer.h"
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
#define MT9V034_MAX_HEIGHT (480) #define MT9V034_MAX_HEIGHT (480)
#define MT9V034_MAX_WIDTH (752) #define MT9V034_MAX_WIDTH (752)
#define MT9V034_CHIP_VERSION (0x00) #define MT9V034_CHIP_VERSION (0x00)
#define MT9V034_COL_START (0x01) #define MT9V034_COL_START (0x01)
#define MT9V034_COL_START_MIN (1) #define MT9V034_COL_START_MIN (1)
@ -33,9 +32,11 @@
#define MT9V034_HORIZONTAL_BLANKING (0x05) #define MT9V034_HORIZONTAL_BLANKING (0x05)
#define MT9V034_HORIZONTAL_BLANKING_MIN (43) #define MT9V034_HORIZONTAL_BLANKING_MIN (43)
#define MT9V034_HORIZONTAL_BLANKING_MAX (1023) #define MT9V034_HORIZONTAL_BLANKING_MAX (1023)
#define MT9V034_HORIZONTAL_BLANKING_DEF (94)
#define MT9V034_VERTICAL_BLANKING (0x06) #define MT9V034_VERTICAL_BLANKING (0x06)
#define MT9V034_VERTICAL_BLANKING_MIN (4) #define MT9V034_VERTICAL_BLANKING_MIN (4)
#define MT9V034_VERTICAL_BLANKING_MAX (3000) #define MT9V034_VERTICAL_BLANKING_MAX (3000)
#define MT9V034_VERTICAL_BLANKING_DEF (45)
#define MT9V034_CHIP_CONTROL (0x07) #define MT9V034_CHIP_CONTROL (0x07)
#define MT9V034_CHIP_CONTROL_MASTER_MODE (1 << 3) #define MT9V034_CHIP_CONTROL_MASTER_MODE (1 << 3)
#define MT9V034_CHIP_CONTROL_DOUT_ENABLE (1 << 7) #define MT9V034_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
@ -57,8 +58,8 @@
#define MT9V034_READ_MODE_DARK_COLS (1 << 6) #define MT9V034_READ_MODE_DARK_COLS (1 << 6)
#define MT9V034_READ_MODE_DARK_ROWS (1 << 7) #define MT9V034_READ_MODE_DARK_ROWS (1 << 7)
#define MT9V034_PIXEL_OPERATION_MODE (0x0F) #define MT9V034_PIXEL_OPERATION_MODE (0x0F)
#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 2) #define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 6) #define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
#define MT9V034_ANALOG_GAIN (0x35) #define MT9V034_ANALOG_GAIN (0x35)
#define MT9V034_ANALOG_GAIN_MIN (16) #define MT9V034_ANALOG_GAIN_MIN (16)
#define MT9V034_ANALOG_GAIN_MAX (64) #define MT9V034_ANALOG_GAIN_MAX (64)
@ -94,42 +95,74 @@
#define MT9V034_AEC_ENABLE (1 << 0) #define MT9V034_AEC_ENABLE (1 << 0)
#define MT9V034_AGC_ENABLE (1 << 1) #define MT9V034_AGC_ENABLE (1 << 1)
#define MT9V034_THERMAL_INFO (0xC1) #define MT9V034_THERMAL_INFO (0xC1)
#define MT9V034_ID_REG (0x6B)
#define MT9V034_WINDOW_HEIGHT_A (0x03)
#define MT9V034_WINDOW_WIDTH_A (0x04)
#define MT9V034_HORIZONTAL_BLANKING_A (0x05)
#define MT9V034_VERTICAL_BLANKING_A (0x06)
#define MT9V034_COARSE_SHUTTER_WIDTH_TOTAL_A (0x0B)
#define MT9V034_ANALOG_GAIN_CONTROL (0x35)
#define MT9V034_MAX_GAIN (0xAB) #define MT9V034_MAX_GAIN (0xAB)
#define MT9V034_FINE_SHUTTER_WIDTH_TOTAL_A (0xD5) #define MT9V034_MAX_EXPOSE (0xAD)
#define MT9V034_PIXEL_COUNT (0xB0)
#define MT9V034_FINE_SHUTTER_WIDTH_TOTAL (0xD5)
#define MICROSECOND_CLKS (1000000)
static bool sensor_has_cfa = false;
static int reset(sensor_t *sensor) static int reset(sensor_t *sensor)
{ {
// NOTE: TODO This doesn't reset register configuration. DCMI_PWDN_HIGH();
cambus_writew(sensor->slv_addr, MT9V034_RESET, 1); systick_sleep(1);
// Delay 10 ms DCMI_PWDN_LOW();
systick_sleep(10); systick_sleep(1);
DCMI_RESET_LOW();
systick_sleep(1);
DCMI_RESET_HIGH();
systick_sleep(1);
uint16_t reg_data;
int ret = 0;
// Setup reconmended reserved register settings.
ret |= cambus_writew(sensor->slv_addr, 0x13, 0x2D2E);
ret |= cambus_writew(sensor->slv_addr, 0x20, 0x01C7);
ret |= cambus_writew(sensor->slv_addr, 0x24, 0x001B);
ret |= cambus_writew(sensor->slv_addr, 0x2B, 0x0003);
ret |= cambus_writew(sensor->slv_addr, 0x2F, 0x0003);
ret |= cambus_writew(sensor->slv_addr, MT9V034_READ_MODE,
MT9V034_READ_MODE_ROW_FLIP | MT9V034_READ_MODE_COL_FLIP);
ret |= cambus_writew(sensor->slv_addr, MT9V034_PIXEL_OPERATION_MODE,
MT9V034_PIXEL_OPERATION_MODE_HDR | MT9V034_PIXEL_OPERATION_MODE_COLOR);
ret |= cambus_readw(sensor->slv_addr, MT9V034_ID_REG, &reg_data);
sensor_has_cfa = ((reg_data >> 9) & 0x7) == 0x6;
cambus_writew(sensor->slv_addr, MT9V034_CHIP_CONTROL, 0x0088);
cambus_writew(sensor->slv_addr, MT9V034_READ_MODE,
(MT9V034_READ_MODE_ROW_FLIP | MT9V034_READ_MODE_COL_FLIP));
cambus_writew(sensor->slv_addr, MT9V034_RESET, 1);
return 0; return 0;
} }
static int sleep(sensor_t *sensor, int enable) static int sleep(sensor_t *sensor, int enable)
{ {
if (enable) {
DCMI_PWDN_HIGH();
systick_sleep(1);
} else {
DCMI_PWDN_LOW();
systick_sleep(1);
}
return 0; return 0;
} }
static int read_reg(sensor_t *sensor, uint8_t reg_addr) static int read_reg(sensor_t *sensor, uint8_t reg_addr)
{ {
uint16_t reg_data; uint16_t reg_data;
if (cambus_readw(sensor->slv_addr, reg_addr, &reg_data) != 0) { if (cambus_readw(sensor->slv_addr, reg_addr, &reg_data) != 0) {
return -1; return -1;
} }
return reg_data; return reg_data;
} }
@ -145,30 +178,45 @@ static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
static int set_framesize(sensor_t *sensor, framesize_t framesize) static int set_framesize(sensor_t *sensor, framesize_t framesize)
{ {
int ret=0; uint16_t width = resolution[framesize][0];
uint16_t readmode = 0;
uint16_t width = resolution[framesize][0];
uint16_t height = resolution[framesize][1]; uint16_t height = resolution[framesize][1];
if ((width * 4) <= MT9V034_MAX_WIDTH && (height * 4) <= MT9V034_MAX_HEIGHT) { if ((width > MT9V034_MAX_WIDTH) || (height > MT9V034_MAX_HEIGHT)) {
width *= 4; height *= 4; return -1;
readmode |= MT9V034_READ_MODE_ROW_BIN_4;
readmode |= MT9V034_READ_MODE_COL_BIN_4;
} else if ((width * 2) <= MT9V034_MAX_WIDTH && (height * 2) <= MT9V034_MAX_HEIGHT) {
width *= 2; height *= 2;
readmode |= MT9V034_READ_MODE_ROW_BIN_2;
readmode |= MT9V034_READ_MODE_COL_BIN_2;
} }
readmode |= MT9V034_READ_MODE_ROW_FLIP; uint16_t readmode;
readmode |= MT9V034_READ_MODE_COL_FLIP; int ret = 0;
cambus_writew(sensor->slv_addr, MT9V034_READ_MODE, readmode); ret |= cambus_readw(sensor->slv_addr, MT9V034_READ_MODE, &readmode);
readmode &= 0xFFF0;
ret |= cambus_writew(sensor->slv_addr, MT9V034_WINDOW_WIDTH, width); if (((width * 4) <= MT9V034_MAX_WIDTH) && ((height * 4) <= MT9V034_MAX_HEIGHT)) {
ret |= cambus_writew(sensor->slv_addr, MT9V034_COL_START, (MT9V034_MAX_WIDTH - width ) / 2 + MT9V034_COL_START_MIN); width *= 4;
height *= 4;
if ((!sensor_has_cfa) || (sensor->pixformat == PIXFORMAT_GRAYSCALE)) {
readmode |= MT9V034_READ_MODE_COL_BIN_4 | MT9V034_READ_MODE_ROW_BIN_4;
}
} else if (((width * 2) <= MT9V034_MAX_WIDTH) && ((height * 2) <= MT9V034_MAX_HEIGHT)) {
width *= 2;
height *= 2;
if ((!sensor_has_cfa) || (sensor->pixformat == PIXFORMAT_GRAYSCALE)) {
readmode |= MT9V034_READ_MODE_COL_BIN_2 | MT9V034_READ_MODE_ROW_BIN_2;
}
}
ret |= cambus_writew(sensor->slv_addr, MT9V034_WINDOW_HEIGHT, height); ret |= cambus_writew(sensor->slv_addr, MT9V034_COL_START, ((MT9V034_MAX_WIDTH - width) / 2) + MT9V034_COL_START_MIN);
ret |= cambus_writew(sensor->slv_addr, MT9V034_ROW_START, (MT9V034_MAX_HEIGHT - height) / 2 + MT9V034_ROW_START_MIN); ret |= cambus_writew(sensor->slv_addr, MT9V034_ROW_START, ((MT9V034_MAX_HEIGHT - height) / 2) + MT9V034_ROW_START_MIN);
ret |= cambus_writew(sensor->slv_addr, MT9V034_WINDOW_WIDTH, width);
ret |= cambus_writew(sensor->slv_addr, MT9V034_WINDOW_HEIGHT, height);
// Notes: 1. The MT9V034 uses column parallel analog-digital converters, thus short row timing is not possible.
// The minimum total row time is 690 columns (horizontal width + horizontal blanking). The minimum
// horizontal blanking is 61. When the window width is set below 627, horizontal blanking
// must be increased.
ret |= cambus_writew(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING,
MT9V034_HORIZONTAL_BLANKING_DEF + (MT9V034_MAX_WIDTH - width));
ret |= cambus_writew(sensor->slv_addr, MT9V034_READ_MODE, readmode);
ret |= cambus_writew(sensor->slv_addr, MT9V034_PIXEL_COUNT,
(resolution[framesize][0] * resolution[framesize][1]) / 8);
return 0; return 0;
} }
@ -185,7 +233,6 @@ static int set_contrast(sensor_t *sensor, int level)
static int set_brightness(sensor_t *sensor, int level) static int set_brightness(sensor_t *sensor, int level)
{ {
return 0; return 0;
} }
static int set_saturation(sensor_t *sensor, int level) static int set_saturation(sensor_t *sensor, int level)
@ -198,7 +245,22 @@ static int set_gainceiling(sensor_t *sensor, gainceiling_t gainceiling)
return 0; return 0;
} }
static int set_quality(sensor_t *sensor, int quality)
{
return 0;
}
static int set_colorbar(sensor_t *sensor, int enable) static int set_colorbar(sensor_t *sensor, int enable)
{
uint16_t test;
int ret = cambus_readw(sensor->slv_addr, MT9V034_TEST_PATTERN, &test);
ret |= cambus_writew(sensor->slv_addr, MT9V034_TEST_PATTERN,
(test & (~(MT9V034_TEST_PATTERN_ENABLE | MT9V034_TEST_PATTERN_GRAY_MASK)))
| ((enable != 0) ? (MT9V034_TEST_PATTERN_ENABLE | MT9V034_TEST_PATTERN_GRAY_VERTICAL) : 0));
return ret;
}
static int set_special_effect(sensor_t *sensor, sde_t sde)
{ {
return 0; return 0;
} }
@ -213,8 +275,8 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
if ((enable == 0) && (!isnanf(gain_db)) && (!isinff(gain_db))) { if ((enable == 0) && (!isnanf(gain_db)) && (!isinff(gain_db))) {
int gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((gain_db / 20.0) * fast_log(10.0)) * 16.0), 127), 0); int gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((gain_db / 20.0) * fast_log(10.0)) * 16.0), 127), 0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, &reg); ret |= cambus_readw(sensor->slv_addr, MT9V034_ANALOG_GAIN, &reg);
ret |= cambus_writew(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, (reg & 0xFF80) | gain); ret |= cambus_writew(sensor->slv_addr, MT9V034_ANALOG_GAIN, (reg & 0xFF80) | gain);
} else if ((enable != 0) && (!isnanf(gain_db_ceiling)) && (!isinff(gain_db_ceiling))) { } else if ((enable != 0) && (!isnanf(gain_db_ceiling)) && (!isinff(gain_db_ceiling))) {
int gain_ceiling = IM_MAX(IM_MIN(fast_roundf(fast_expf((gain_db_ceiling / 20.0) * fast_log(10.0)) * 16.0), 127), 16); int gain_ceiling = IM_MAX(IM_MIN(fast_roundf(fast_expf((gain_db_ceiling / 20.0) * fast_log(10.0)) * 16.0), 127), 16);
@ -228,7 +290,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
static int get_gain_db(sensor_t *sensor, float *gain_db) static int get_gain_db(sensor_t *sensor, float *gain_db)
{ {
uint16_t gain; uint16_t gain;
int ret = cambus_readw(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, &gain); int ret = cambus_readw(sensor->slv_addr, MT9V034_ANALOG_GAIN, &gain);
*gain_db = 20.0 * (fast_log((gain & 0x7F) / 16.0) / fast_log(10.0)); *gain_db = 20.0 * (fast_log((gain & 0x7F) / 16.0) / fast_log(10.0));
@ -237,24 +299,22 @@ static int get_gain_db(sensor_t *sensor, float *gain_db)
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us) static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
{ {
uint16_t reg, row_limit_0, row_limit_1, row_time_0, row_time_1; uint16_t reg, row_time_0, row_time_1;
int ret = cambus_readw(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE, &reg); int ret = cambus_readw(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE, &reg);
ret |= cambus_writew(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE, ret |= cambus_writew(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE,
(reg & (~MT9V034_AEC_ENABLE)) | ((enable != 0) ? MT9V034_AEC_ENABLE : 0)); (reg & (~MT9V034_AEC_ENABLE)) | ((enable != 0) ? MT9V034_AEC_ENABLE : 0));
if ((enable == 0) && (exposure_us >= 0)) { if ((enable == 0) && (exposure_us >= 0)) {
ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_HEIGHT_A, &row_limit_0); ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_WIDTH, &row_time_0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_VERTICAL_BLANKING_A, &row_limit_1); ret |= cambus_readw(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING, &row_time_1);
ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_WIDTH_A, &row_time_0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING_A, &row_time_1);
int exposure = exposure_us * (27000000 / 1000000); int exposure = IM_MIN(exposure_us, MICROSECOND_CLKS / 2) * (MT9V034_XCLK_FREQ / MICROSECOND_CLKS);
int row_time = row_time_0 + row_time_1; int row_time = row_time_0 + row_time_1;
int coarse_time = IM_MIN((exposure / row_time), (row_limit_0 + row_limit_1)); int coarse_time = exposure / row_time;
int fine_time = exposure % row_time; int fine_time = exposure % row_time;
ret |= cambus_writew(sensor->slv_addr, MT9V034_COARSE_SHUTTER_WIDTH_TOTAL_A, coarse_time); ret |= cambus_writew(sensor->slv_addr, MT9V034_TOTAL_SHUTTER_WIDTH, coarse_time);
ret |= cambus_writew(sensor->slv_addr, MT9V034_FINE_SHUTTER_WIDTH_TOTAL_A, fine_time); ret |= cambus_writew(sensor->slv_addr, MT9V034_FINE_SHUTTER_WIDTH_TOTAL, fine_time);
} }
return ret; return ret;
@ -263,12 +323,12 @@ static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
static int get_exposure_us(sensor_t *sensor, int *exposure_us) static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{ {
uint16_t int_rows, int_pixels, row_time_0, row_time_1; uint16_t int_rows, int_pixels, row_time_0, row_time_1;
int ret = cambus_readw(sensor->slv_addr, MT9V034_COARSE_SHUTTER_WIDTH_TOTAL_A, &int_rows); int ret = cambus_readw(sensor->slv_addr, MT9V034_TOTAL_SHUTTER_WIDTH, &int_rows);
ret |= cambus_readw(sensor->slv_addr, MT9V034_FINE_SHUTTER_WIDTH_TOTAL_A, &int_pixels); ret |= cambus_readw(sensor->slv_addr, MT9V034_FINE_SHUTTER_WIDTH_TOTAL, &int_pixels);
ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_WIDTH_A, &row_time_0); ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_WIDTH, &row_time_0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING_A, &row_time_1); ret |= cambus_readw(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING, &row_time_1);
*exposure_us = ((int_rows * (row_time_0 + row_time_1)) + int_pixels) / (27000000 / 1000000); *exposure_us = ((int_rows * (row_time_0 + row_time_1)) + int_pixels) / (MT9V034_XCLK_FREQ / MICROSECOND_CLKS);
return ret; return ret;
} }
@ -287,9 +347,8 @@ static int set_hmirror(sensor_t *sensor, int enable)
{ {
uint16_t read_mode; uint16_t read_mode;
int ret = cambus_readw(sensor->slv_addr, MT9V034_READ_MODE, &read_mode); int ret = cambus_readw(sensor->slv_addr, MT9V034_READ_MODE, &read_mode);
ret |= cambus_writew(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, ret |= cambus_writew(sensor->slv_addr, MT9V034_READ_MODE, // inverted behavior
(read_mode & (~MT9V034_READ_MODE_COL_FLIP)) | ((enable != 0) ? MT9V034_READ_MODE_COL_FLIP : 0)); (read_mode & (~MT9V034_READ_MODE_COL_FLIP)) | ((enable == 0) ? MT9V034_READ_MODE_COL_FLIP : 0));
return ret; return ret;
} }
@ -297,17 +356,11 @@ static int set_vflip(sensor_t *sensor, int enable)
{ {
uint16_t read_mode; uint16_t read_mode;
int ret = cambus_readw(sensor->slv_addr, MT9V034_READ_MODE, &read_mode); int ret = cambus_readw(sensor->slv_addr, MT9V034_READ_MODE, &read_mode);
ret |= cambus_writew(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, ret |= cambus_writew(sensor->slv_addr, MT9V034_READ_MODE, // inverted behavior
(read_mode & (~MT9V034_READ_MODE_ROW_FLIP)) | ((enable != 0) ? MT9V034_READ_MODE_ROW_FLIP : 0)); (read_mode & (~MT9V034_READ_MODE_ROW_FLIP)) | ((enable == 0) ? MT9V034_READ_MODE_ROW_FLIP : 0));
return ret; return ret;
} }
static int set_special_effect(sensor_t *sensor, sde_t sde)
{
return 0;
}
static int set_lens_correction(sensor_t *sensor, int enable, int radi, int coef) static int set_lens_correction(sensor_t *sensor, int enable, int radi, int coef)
{ {
return 0; return 0;
@ -315,8 +368,7 @@ static int set_lens_correction(sensor_t *sensor, int enable, int radi, int coef)
int mt9v034_init(sensor_t *sensor) int mt9v034_init(sensor_t *sensor)
{ {
// Initialize sensor structure. sensor->gs_bpp = sizeof(uint8_t);
sensor->gs_bpp = 1;
sensor->reset = reset; sensor->reset = reset;
sensor->sleep = sleep; sensor->sleep = sleep;
sensor->read_reg = read_reg; sensor->read_reg = read_reg;
@ -328,6 +380,7 @@ int mt9v034_init(sensor_t *sensor)
sensor->set_brightness = set_brightness; sensor->set_brightness = set_brightness;
sensor->set_saturation = set_saturation; sensor->set_saturation = set_saturation;
sensor->set_gainceiling = set_gainceiling; sensor->set_gainceiling = set_gainceiling;
sensor->set_quality = set_quality;
sensor->set_colorbar = set_colorbar; sensor->set_colorbar = set_colorbar;
sensor->set_auto_gain = set_auto_gain; sensor->set_auto_gain = set_auto_gain;
sensor->get_gain_db = get_gain_db; sensor->get_gain_db = get_gain_db;
@ -340,7 +393,6 @@ int mt9v034_init(sensor_t *sensor)
sensor->set_special_effect = set_special_effect; sensor->set_special_effect = set_special_effect;
sensor->set_lens_correction = set_lens_correction; sensor->set_lens_correction = set_lens_correction;
// Set sensor flags
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_VSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_VSYNC, 0);
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_HSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_HSYNC, 0);
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 0);