Merge pull request #1370 from kwagyeman/kwabena/mt9m114_final

Finish MT9M114 driver
This commit is contained in:
Ibrahim Abd Elkader 2021-06-19 22:01:15 +02:00 committed by GitHub
commit 3fb5bf1d21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 151 additions and 19 deletions

View File

@ -38,7 +38,7 @@
#define OV7725_ID (0x77) #define OV7725_ID (0x77)
#define OV9650_ID (0x96) #define OV9650_ID (0x96)
#define MT9V034_ID (0x13) #define MT9V034_ID (0x13)
#define MT9M114_ID (0x81) #define MT9M114_ID (0x2481)
#define LEPTON_ID (0x54) #define LEPTON_ID (0x54)
#define HM01B0_ID (0xB0) #define HM01B0_ID (0xB0)
#define GC2145_ID (0x21) #define GC2145_ID (0x21)

View File

@ -579,8 +579,8 @@ int sensor_init()
} }
init_ret = paj6100_init(&sensor); init_ret = paj6100_init(&sensor);
break; break;
#endif // (OMV_ENABLE_PAJ6100 == 1) #endif // (OMV_ENABLE_PAJ6100 == 1)
default: default:
return -3; return -3;
break; break;

View File

@ -40,13 +40,7 @@ static uint16_t readout_w = ACTIVE_SENSOR_WIDTH;
static uint16_t readout_h = ACTIVE_SENSOR_HEIGHT; static uint16_t readout_h = ACTIVE_SENSOR_HEIGHT;
static const uint16_t default_regs[][2] = { static const uint16_t default_regs[][2] = {
// XMDA // Sensor Optimization
{0x098E, 0x0000},
// PLL Settings
{0xC980, 0x0120},
// Sesnor Optimization
{0x316A, 0x8270}, {0x316A, 0x8270},
{0x316C, 0x8270}, {0x316C, 0x8270},
{0x3ED0, 0x2305}, {0x3ED0, 0x2305},
@ -305,8 +299,8 @@ static int load_and_apply_patch(sensor_t *sensor, uint16_t patch_address, const
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_XMDA_ACCESS_CTL_STAT, patch_address >> 15); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_XMDA_ACCESS_CTL_STAT, patch_address >> 15);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_XMDA_PHYSICAL_ADDRESS_ACCESS, patch_address & 0x7FFF); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_XMDA_PHYSICAL_ADDRESS_ACCESS, patch_address & 0x7FFF);
ret |= load_array(sensor, patch_address, patch, patch_len); ret |= load_array(sensor, patch_address, patch, patch_len);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_XMDA_LOGIC_ADDRESS_ACCESS, 0x0000); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_XMDA_LOGIC_ADDRESS_ACCESS, 0x0000);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_PATCHLDR_LOADER_ADDRESS, patch_loader_address); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_PATCHLDR_LOADER_ADDRESS, patch_loader_address);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_PATCHLDR_PATCH_ID, patch_id); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_PATCHLDR_PATCH_ID, patch_id);
@ -472,6 +466,11 @@ static int reset(sensor_t *sensor)
ret |= cambus_readw2(&sensor->bus, sensor->slv_addr, 0x301A, &reg); ret |= cambus_readw2(&sensor->bus, sensor->slv_addr, 0x301A, &reg);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, 0x301A, reg | (1 << 9)); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, 0x301A, reg | (1 << 9));
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_SYSCTL_PLL_DIVIDER_M_N,
(sensor_xclk_freq() == MT9M114_XCLK_FREQ)
? 0x120 // xclk=24MHz, m=32, n=1, sensor=48MHz, bus=76.8MHz
: 0x448); // xclk=25MHz, m=72, n=4, sensor=45MHz, bus=72MHz
for (int i = 0; i < (sizeof(default_regs) / sizeof(default_regs[0])); i++) { for (int i = 0; i < (sizeof(default_regs) / sizeof(default_regs[0])); i++) {
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, default_regs[i][0], default_regs[i][1]); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, default_regs[i][0], default_regs[i][1]);
} }
@ -667,6 +666,11 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_Y_ADDR_END, sensor_he); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_Y_ADDR_END, sensor_he);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_X_ADDR_END, sensor_we); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_X_ADDR_END, sensor_we);
int pixclk = (sensor_xclk_freq() == MT9M114_XCLK_FREQ) ? 48000000 : 45000000;
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_PIXCLK, pixclk >> 16);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_PIXCLK + 2, pixclk);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MIN, ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MIN,
(read_mode_div == 2) ? 451 : 219); // figured this out by checking register wizard against datasheet (read_mode_div == 2) ? 451 : 219); // figured this out by checking register wizard against datasheet
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MAX, ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MAX,
@ -690,7 +694,7 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_OUTPUT_WIDTH, w); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_OUTPUT_WIDTH, w);
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_OUTPUT_HEIGHT, h); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_OUTPUT_HEIGHT, h);
float rate = (48000000.f / (frame_length_lines * line_length_pck)) * 256; float rate = (((float) pixclk) / (frame_length_lines * line_length_pck)) * 256;
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_AET_MAX_FRAME_RATE, fast_ceilf(rate)); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_AET_MAX_FRAME_RATE, fast_ceilf(rate));
ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_AET_MIN_FRAME_RATE, fast_floorf(rate / 2.f)); ret |= cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_AET_MIN_FRAME_RATE, fast_floorf(rate / 2.f));
@ -711,17 +715,67 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
return change_config(sensor); return change_config(sensor);
} }
static int set_contrast(sensor_t *sensor, int level) static int set_framerate(sensor_t *sensor, int framerate)
{ {
return 0; if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_AET_MAX_FRAME_RATE, framerate * 256) != 0) {
return -1;
}
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_CAM_AET_MIN_FRAME_RATE, framerate * 128) != 0) {
return -1;
}
return change_config(sensor);
} }
static int set_brightness(sensor_t *sensor, int level) static int set_contrast(sensor_t *sensor, int level) // -16 to +16
{ {
return 0; int new_level = (level > 0) ? (level * 2) : level;
if ((new_level < -16) || (32 < new_level)) {
return -1;
}
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_CONTRAST_CONTROL, new_level + 32) != 0) {
return -1;
}
return refresh(sensor);
} }
static int set_saturation(sensor_t *sensor, int level) static int set_brightness(sensor_t *sensor, int level) // -16 to +16
{
int new_level = level * 2;
if ((new_level < -32) || (32 < new_level)) {
return -1;
}
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_BRIGHTNESS_CONTROL, new_level + 55) != 0) {
return -1;
}
return refresh(sensor);
}
static int set_saturation(sensor_t *sensor, int level) // -16 to +16
{
int new_level = level * 8;
if ((new_level < -128) || (128 < new_level)) {
return -1;
}
new_level = IM_MIN(new_level, 127);
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_SATURATION_CONTROL, new_level + 128) != 0) {
return -1;
}
return refresh(sensor);
}
static int set_gainceiling(sensor_t *sensor, gainceiling_t gainceiling)
{ {
return 0; return 0;
} }
@ -737,31 +791,93 @@ static int set_colorbar(sensor_t *sensor, int enable)
static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain_db_ceiling) static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain_db_ceiling)
{ {
return 0; if (cambus_writeb2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_AE_MODE_CONTROL, enable ? 0x2 : 0x1) != 0) {
return -1;
}
if ((enable == 0) && (!isnanf(gain_db)) && (!isinff(gain_db))) {
int gain = IM_MAX(IM_MIN(fast_expf((gain_db / 20.f) * fast_log(10.f)) * 32.f, 0xffff), 0x0000);
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_GAIN_CONTROL, gain) != 0) {
return -1;
}
}
return refresh(sensor);
} }
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;
if (cambus_readw2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_GAIN_CONTROL, &gain) != 0) {
return -1;
}
*gain_db = 20.f * (fast_log(gain / 32.f) / fast_log(10.f));
return 0; return 0;
} }
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)
{ {
return 0; if (cambus_writeb2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_AE_MODE_CONTROL, enable ? 0x2 : 0x1) != 0) {
return -1;
}
if ((enable == 0) && (exposure_us >= 0)) {
if (cambus_writeb2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_MANUAL_EXPOSURE_CONFIG, 0x1) != 0) {
return -1;
}
int exposure_100_us = exposure_us / 100;
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_EXPOSURE_TIME_ABSOLUTE_CTRL,
exposure_100_us >> 16) != 0) {
return -1;
}
if (cambus_writew2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_EXPOSURE_TIME_ABSOLUTE_CTRL + 2,
exposure_100_us) != 0) {
return -1;
}
}
return refresh(sensor);
} }
static int get_exposure_us(sensor_t *sensor, int *exposure_us) static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{ {
uint16_t reg_h, reg_l;
if (cambus_readw2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_EXPOSURE_TIME_ABSOLUTE_CTRL, &reg_h) != 0) {
return -1;
}
if (cambus_readw2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_EXPOSURE_TIME_ABSOLUTE_CTRL + 2, &reg_l) != 0) {
return -1;
}
*exposure_us = ((reg_h << 16) | reg_l) * 100;
return 0; return 0;
} }
static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db) static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{ {
if (cambus_writeb2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_WHITE_BALANCE_AUTO_CONTROL, enable ? 0x1 : 0x0) != 0) {
return -1;
}
return 0; return 0;
} }
static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db) static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db)
{ {
*r_gain_db = 0;
*g_gain_db = 0;
*b_gain_db = 0;
return 0; return 0;
} }
@ -872,9 +988,11 @@ int mt9m114_init(sensor_t *sensor)
sensor->write_reg = write_reg; sensor->write_reg = write_reg;
sensor->set_pixformat = set_pixformat; sensor->set_pixformat = set_pixformat;
sensor->set_framesize = set_framesize; sensor->set_framesize = set_framesize;
sensor->set_framerate = set_framerate;
sensor->set_contrast = set_contrast; sensor->set_contrast = set_contrast;
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_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;

View File

@ -8,6 +8,8 @@
* *
* MT9M114 driver. * MT9M114 driver.
*/ */
#ifndef __REG_REGS_H__
#define __REG_REGS_H__
#define MT9M114_REG_PAD_SLEW (0x001E) #define MT9M114_REG_PAD_SLEW (0x001E)
@ -63,6 +65,7 @@
#define MT9M114_REG_SENSOR_CFG_X_ADDR_START (0xC802) #define MT9M114_REG_SENSOR_CFG_X_ADDR_START (0xC802)
#define MT9M114_REG_SENSOR_CFG_Y_ADDR_END (0xC804) #define MT9M114_REG_SENSOR_CFG_Y_ADDR_END (0xC804)
#define MT9M114_REG_SENSOR_CFG_X_ADDR_END (0xC806) #define MT9M114_REG_SENSOR_CFG_X_ADDR_END (0xC806)
#define MT9M114_REG_SENSOR_CFG_PIXCLK (0xC808)
#define MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MIN (0xC80E) #define MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MIN (0xC80E)
#define MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MAX (0xC810) #define MT9M114_REG_SENSOR_CFG_FINE_INTEG_TIME_MAX (0xC810)
@ -115,6 +118,15 @@
#define MT9M114_REG_CAM_SYSCTL_PLL_DIVIDER_M_N (0xC980) #define MT9M114_REG_CAM_SYSCTL_PLL_DIVIDER_M_N (0xC980)
#define MT9M114_REG_CAM_PORT_OUTPUT_CONTROL (0xC984) #define MT9M114_REG_CAM_PORT_OUTPUT_CONTROL (0xC984)
#define MT9M114_REG_UVC_AE_MODE_CONTROL (0xCC00)
#define MT9M114_REG_UVC_WHITE_BALANCE_AUTO_CONTROL (0xCC01)
#define MT9M114_REG_UVC_EXPOSURE_TIME_ABSOLUTE_CTRL (0xCC04)
#define MT9M114_REG_UVC_BRIGHTNESS_CONTROL (0xCC0A)
#define MT9M114_REG_UVC_CONTRAST_CONTROL (0xCC0C)
#define MT9M114_REG_UVC_GAIN_CONTROL (0xCC0E)
#define MT9M114_REG_UVC_SATURATION_CONTROL (0xCC12)
#define MT9M114_REG_UVC_MANUAL_EXPOSURE_CONFIG (0xCC20)
#define MT9M114_REG_SYSMGR_NEXT_STATE (0xDC00) #define MT9M114_REG_SYSMGR_NEXT_STATE (0xDC00)
#define MT9M114_REG_SYSMGR_CURRENT_STATE (0xDC01) #define MT9M114_REG_SYSMGR_CURRENT_STATE (0xDC01)
#define MT9M114_REG_SYSMGR_CMD_STATUS (0xDC02) #define MT9M114_REG_SYSMGR_CMD_STATUS (0xDC02)
@ -129,3 +141,5 @@
#define MT9M114_REG_CMD_HANDLE_WAIT_EVENT_ID (0xFC00) #define MT9M114_REG_CMD_HANDLE_WAIT_EVENT_ID (0xFC00)
#define MT9M114_REG_CMD_HANDLE_NUM_EVENTS (0xFC02) #define MT9M114_REG_CMD_HANDLE_NUM_EVENTS (0xFC02)
#endif //__REG_REGS_H__