mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #1370 from kwagyeman/kwabena/mt9m114_final
Finish MT9M114 driver
This commit is contained in:
commit
3fb5bf1d21
@ -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)
|
||||||
|
|||||||
@ -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, ®);
|
ret |= cambus_readw2(&sensor->bus, sensor->slv_addr, 0x301A, ®);
|
||||||
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, ®_h) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cambus_readw2(&sensor->bus, sensor->slv_addr, MT9M114_REG_UVC_EXPOSURE_TIME_ABSOLUTE_CTRL + 2, ®_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;
|
||||||
|
|||||||
@ -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__
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user