Merge pull request #550 from openmv/ov5640

Add support for OV5640
This commit is contained in:
Ibrahim Abd Elkader 2019-07-12 23:35:14 +02:00 committed by GitHub
commit 403ced8074
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 4759 additions and 41 deletions

View File

@ -168,6 +168,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
ov9650.o \
ov2640.o \
ov7725.o \
ov5640.o \
mt9v034.o \
lepton.o \
sensor.o \
@ -443,6 +444,7 @@ UVC_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
ov9650.o \
ov2640.o \
ov7725.o \
ov5640.o \
mt9v034.o \
lepton.o \
sensor.o \

View File

@ -14,6 +14,7 @@ SRCS += $(addprefix , \
ov9650.c \
ov2640.c \
ov7725.c \
ov5640.c \
mt9v034.c \
lepton.c \
sensor.c \

View File

@ -80,6 +80,30 @@ int cambus_writeb(uint8_t slv_addr, uint8_t reg_addr, uint8_t reg_data)
return ret;
}
int cambus_readb2(uint8_t slv_addr, uint16_t reg_addr, uint8_t *reg_data)
{
int ret=0;
__disable_irq();
if (HAL_I2C_Mem_Read(&I2CHandle, slv_addr, reg_addr,
I2C_MEMADD_SIZE_16BIT, reg_data, 1, I2C_TIMEOUT) != HAL_OK) {
ret = -1;
}
__enable_irq();
return ret;
}
int cambus_writeb2(uint8_t slv_addr, uint16_t reg_addr, uint8_t reg_data)
{
int ret=0;
__disable_irq();
if (HAL_I2C_Mem_Write(&I2CHandle, slv_addr, reg_addr,
I2C_MEMADD_SIZE_16BIT, &reg_data, 1, I2C_TIMEOUT) != HAL_OK) {
ret = -1;
}
__enable_irq();
return ret;
}
int cambus_readw(uint8_t slv_addr, uint8_t reg_addr, uint16_t *reg_data)
{
int ret=0;

View File

@ -13,6 +13,8 @@ int cambus_init();
int cambus_scan();
int cambus_readb(uint8_t slv_addr, uint8_t reg_addr, uint8_t *reg_data);
int cambus_writeb(uint8_t slv_addr, uint8_t reg_addr, uint8_t reg_data);
int cambus_readb2(uint8_t slv_addr, uint16_t reg_addr, uint8_t *reg_data);
int cambus_writeb2(uint8_t slv_addr, uint16_t reg_addr, uint8_t reg_data);
int cambus_readw(uint8_t slv_addr, uint8_t reg_addr, uint16_t *reg_data);
int cambus_writew(uint8_t slv_addr, uint8_t reg_addr, uint16_t reg_data);
int cambus_readw2(uint8_t slv_addr, uint16_t reg_addr, uint16_t *reg_data);

View File

@ -115,7 +115,7 @@ static int sleep(sensor_t *sensor, int enable)
return 0;
}
static int read_reg(sensor_t *sensor, uint8_t reg_addr)
static int read_reg(sensor_t *sensor, uint16_t reg_addr)
{
uint16_t reg_data;
if (cambus_readw2(sensor->slv_addr, reg_addr, &reg_data)) {
@ -124,7 +124,7 @@ static int read_reg(sensor_t *sensor, uint8_t reg_addr)
return reg_data;
}
static int write_reg(sensor_t *sensor, uint8_t reg_addr, uint16_t reg_data)
static int write_reg(sensor_t *sensor, uint16_t reg_addr, uint16_t reg_data)
{
return cambus_writew2(sensor->slv_addr, reg_addr, reg_data);
}

View File

@ -148,7 +148,7 @@ static int sleep(sensor_t *sensor, int enable)
return 0;
}
static int read_reg(sensor_t *sensor, uint8_t reg_addr)
static int read_reg(sensor_t *sensor, uint16_t reg_addr)
{
uint16_t reg_data;
@ -159,7 +159,7 @@ static int read_reg(sensor_t *sensor, uint8_t reg_addr)
return reg_data;
}
static int write_reg(sensor_t *sensor, uint8_t reg_addr, uint16_t reg_data)
static int write_reg(sensor_t *sensor, uint16_t reg_addr, uint16_t reg_data)
{
return cambus_writew(sensor->slv_addr, reg_addr, reg_data);
}

239
src/omv/ov5640.c Normal file
View File

@ -0,0 +1,239 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* OV5640 driver.
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include STM32_HAL_H
#include "cambus.h"
#include "ov5640.h"
#include "ov5640_regs.h"
#include "systick.h"
#include "omv_boardconfig.h"
static int reset(sensor_t *sensor)
{
int i=0;
const uint16_t (*regs)[2];
// Reset all registers
cambus_writeb2(sensor->slv_addr, 0x3008, 0x42);
// Delay 10 ms
systick_sleep(10);
// Write default regsiters
for (i=0, regs = default_regs; regs[i][0]; i++) {
cambus_writeb2(sensor->slv_addr, regs[i][0], regs[i][1]);
}
cambus_writeb2(sensor->slv_addr, 0x3008, 0x02);
systick_sleep(30);
// Write auto focus firmware
for (i=0, regs = OV5640_AF_REG; regs[i][0]; i++) {
cambus_writeb2(sensor->slv_addr, regs[i][0], regs[i][1]);
}
// Delay
systick_sleep(10);
// Enable auto focus
cambus_writeb2(sensor->slv_addr, 0x3023, 0x01);
cambus_writeb2(sensor->slv_addr, 0x3022, 0x04);
systick_sleep(30);
return 0;
}
static int sleep(sensor_t *sensor, int enable)
{
uint8_t reg;
if (enable) {
reg = 0x42;
} else {
reg = 0x02;
}
// Write back register
return cambus_writeb2(sensor->slv_addr, 0x3008, reg);
}
static int read_reg(sensor_t *sensor, uint16_t reg_addr)
{
uint8_t reg_data;
if (cambus_readb2(sensor->slv_addr, reg_addr, &reg_data) != 0) {
return -1;
}
return reg_data;
}
static int write_reg(sensor_t *sensor, uint16_t reg_addr, uint16_t reg_data)
{
return cambus_writeb2(sensor->slv_addr, reg_addr, reg_data);
}
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
{
// uint8_t reg;
int ret=0;
switch (pixformat) {
case PIXFORMAT_RGB565:
cambus_writeb2(sensor->slv_addr, 0x4300, 0x61);//RGB565
cambus_writeb2(sensor->slv_addr, 0x501f, 0x01);//ISP RGB
break;
case PIXFORMAT_YUV422:
case PIXFORMAT_GRAYSCALE:
cambus_writeb2(sensor->slv_addr, 0x4300, 0x10);//Y8
cambus_writeb2(sensor->slv_addr, 0x501f, 0x00);//ISP YUV
break;
case PIXFORMAT_BAYER:
//reg = 0x00;//TODO: fix order
break;
default:
return -1;
}
return ret;
}
static int set_framesize(sensor_t *sensor, framesize_t framesize)
{
int ret=0;
uint16_t w = resolution[framesize][0];
uint16_t h = resolution[framesize][1];
ret |= cambus_writeb2(sensor->slv_addr, 0x3808, w>>8);
ret |= cambus_writeb2(sensor->slv_addr, 0x3809, w);
ret |= cambus_writeb2(sensor->slv_addr, 0x380a, h>>8);
ret |= cambus_writeb2(sensor->slv_addr, 0x380b, h);
return ret;
}
static int set_framerate(sensor_t *sensor, framerate_t framerate)
{
return 0;
}
static int set_contrast(sensor_t *sensor, int level)
{
return 0;
}
static int set_brightness(sensor_t *sensor, int level)
{
return 0;
}
static int set_saturation(sensor_t *sensor, int level)
{
return 0;
}
static int set_gainceiling(sensor_t *sensor, gainceiling_t gainceiling)
{
return 0;
}
static int set_colorbar(sensor_t *sensor, int enable)
{
return 0;
}
static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain_db_ceiling)
{
return 0;
}
static int get_gain_db(sensor_t *sensor, float *gain_db)
{
return 0;
}
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
{
return 0;
}
static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{
return 0;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{
return 0;
}
static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db)
{
return 0;
}
static int set_hmirror(sensor_t *sensor, int enable)
{
uint8_t reg;
int ret = cambus_readb2(sensor->slv_addr, 0x3821, &reg);
if (enable){
ret |= cambus_writeb2(sensor->slv_addr, 0x3821, reg&0x06);
} else {
ret |= cambus_writeb2(sensor->slv_addr, 0x3821, reg|0xF9);
}
return ret;
}
static int set_vflip(sensor_t *sensor, int enable)
{
uint8_t reg;
int ret = cambus_readb2(sensor->slv_addr, 0x3820, &reg);
if (enable){
ret |= cambus_writeb2(sensor->slv_addr, 0x3820, reg&0xF9);
} else {
ret |= cambus_writeb2(sensor->slv_addr, 0x3820, reg|0x06);
}
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)
{
return 0;
}
int ov5640_init(sensor_t *sensor)
{
// Initialize sensor structure.
sensor->gs_bpp = 1;
sensor->reset = reset;
sensor->sleep = sleep;
sensor->read_reg = read_reg;
sensor->write_reg = write_reg;
sensor->set_pixformat = set_pixformat;
sensor->set_framesize = set_framesize;
sensor->set_framerate = set_framerate;
sensor->set_contrast = set_contrast;
sensor->set_brightness = set_brightness;
sensor->set_saturation = set_saturation;
sensor->set_gainceiling = set_gainceiling;
sensor->set_colorbar = set_colorbar;
sensor->set_auto_gain = set_auto_gain;
sensor->get_gain_db = get_gain_db;
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->get_rgb_gain_db = get_rgb_gain_db;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;
sensor->set_special_effect = set_special_effect;
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_HSYNC, 0);
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1);
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 1);
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 0);
return 0;
}

13
src/omv/ov5640.h Normal file
View File

@ -0,0 +1,13 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* OV5640 driver.
*
*/
#ifndef __OV5640_H__
#define __OV5640_H__
#include "sensor.h"
int ov5640_init(sensor_t *sensor);
#endif // __OV5640_H__

4409
src/omv/ov5640_regs.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -179,7 +179,7 @@ static int sleep(sensor_t *sensor, int enable)
return cambus_writeb(sensor->slv_addr, COM2, reg) | ret;
}
static int read_reg(sensor_t *sensor, uint8_t reg_addr)
static int read_reg(sensor_t *sensor, uint16_t reg_addr)
{
uint8_t reg_data;
if (cambus_readb(sensor->slv_addr, reg_addr, &reg_data) != 0) {
@ -188,7 +188,7 @@ static int read_reg(sensor_t *sensor, uint8_t reg_addr)
return reg_data;
}
static int write_reg(sensor_t *sensor, uint8_t reg_addr, uint16_t reg_data)
static int write_reg(sensor_t *sensor, uint16_t reg_addr, uint16_t reg_data)
{
return cambus_writeb(sensor->slv_addr, reg_addr, reg_data);
}

View File

@ -14,6 +14,7 @@
#include "ov9650.h"
#include "ov2640.h"
#include "ov7725.h"
#include "ov5640.h"
#include "mt9v034.h"
#include "lepton.h"
#include "sensor.h"
@ -21,8 +22,6 @@
#include "framebuffer.h"
#include "omv_boardconfig.h"
#define OV_CHIP_ID (0x0A)
#define ON_CHIP_ID (0x00)
#define MAX_XFER_SIZE (0xFFFC*4)
sensor_t sensor = {0};
@ -305,38 +304,56 @@ int sensor_init()
// Set default snapshot function.
sensor.snapshot = sensor_snapshot;
if (sensor.slv_addr == LEPTON_ID) {
switch (sensor.slv_addr) {
case OV7725_SLV_ADDR:
cambus_readb(sensor.slv_addr, OV_CHIP_ID, &sensor.chip_id);
break;
case OV2640_SLV_ADDR:
cambus_readb(sensor.slv_addr, OV_CHIP_ID, &sensor.chip_id);
break;
case MT9V034_SLV_ADDR:
cambus_readb(sensor.slv_addr, ON_CHIP_ID, &sensor.chip_id);
break;
case LEPTON_SLV_ADDR:
sensor.chip_id = LEPTON_ID;
break;
case OV5640_SLV_ADDR:
cambus_readb2(sensor.slv_addr, OV5640_CHIP_ID, &sensor.chip_id);
break;
default:
return -3;
break;
}
switch (sensor.chip_id)
{
case OV7725_ID:
init_ret = ov7725_init(&sensor);
break;
case MT9V034_ID:
if (extclk_config(MT9V034_XCLK_FREQ) != 0) {
return -3;
}
init_ret = mt9v034_init(&sensor);
break;
case LEPTON_ID:
if (extclk_config(LEPTON_XCLK_FREQ) != 0) {
return -3;
}
init_ret = lepton_init(&sensor);
} else {
// Read ON semi sensor ID.
cambus_readb(sensor.slv_addr, ON_CHIP_ID, &sensor.chip_id);
if (sensor.chip_id == MT9V034_ID) {
if (extclk_config(MT9V034_XCLK_FREQ) != 0) {
return -3;
}
init_ret = mt9v034_init(&sensor);
} else { // Read OV sensor ID.
cambus_readb(sensor.slv_addr, OV_CHIP_ID, &sensor.chip_id);
// Initialize sensor struct.
switch (sensor.chip_id) {
case OV9650_ID:
init_ret = ov9650_init(&sensor);
break;
case OV2640_ID:
init_ret = ov2640_init(&sensor);
break;
case OV7725_ID:
init_ret = ov7725_init(&sensor);
break;
default:
// Sensor is not supported.
return -3;
}
}
break;
case OV5640_ID:
init_ret = ov5640_init(&sensor);
break;
case OV2640_ID:
init_ret = ov2640_init(&sensor);
break;
case OV9650_ID:
init_ret = ov9650_init(&sensor);
break;
default:
return -3;
break;
}
if (init_ret != 0 ) {
@ -423,7 +440,7 @@ int sensor_shutdown(int enable)
return 0;
}
int sensor_read_reg(uint8_t reg_addr)
int sensor_read_reg(uint16_t reg_addr)
{
if (sensor.read_reg == NULL) {
// Operation not supported
@ -432,7 +449,7 @@ int sensor_read_reg(uint8_t reg_addr)
return sensor.read_reg(&sensor, reg_addr);
}
int sensor_write_reg(uint8_t reg_addr, uint16_t reg_data)
int sensor_write_reg(uint16_t reg_addr, uint16_t reg_data)
{
if (sensor.write_reg == NULL) {
// Operation not supported

View File

@ -12,9 +12,20 @@
#include <stdarg.h>
#include "imlib.h"
#define OV7725_SLV_ADDR (0x42)
#define OV2640_SLV_ADDR (0x60)
#define MT9V034_SLV_ADDR (0xB8)
#define LEPTON_SLV_ADDR (0x54)
#define OV5640_SLV_ADDR (0x78)
#define OV_CHIP_ID (0x0A)
#define OV5640_CHIP_ID (0x300A)
#define ON_CHIP_ID (0x00)
#define OV9650_ID (0x96)
#define OV2640_ID (0x26)
#define OV7725_ID (0x77)
#define OV5640_ID (0x56)
#define MT9V034_ID (0x13)
#define LEPTON_ID (0x54)
@ -150,8 +161,8 @@ typedef struct _sensor {
// Sensor function pointers
int (*reset) (sensor_t *sensor);
int (*sleep) (sensor_t *sensor, int enable);
int (*read_reg) (sensor_t *sensor, uint8_t reg_addr);
int (*write_reg) (sensor_t *sensor, uint8_t reg_addr, uint16_t reg_data);
int (*read_reg) (sensor_t *sensor, uint16_t reg_addr);
int (*write_reg) (sensor_t *sensor, uint16_t reg_addr, uint16_t reg_data);
int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
int (*set_framerate) (sensor_t *sensor, framerate_t framerate);
@ -197,10 +208,10 @@ int sensor_sleep(int enable);
int sensor_shutdown(int enable);
// Read a sensor register.
int sensor_read_reg(uint8_t reg_addr);
int sensor_read_reg(uint16_t reg_addr);
// Write a sensor register.
int sensor_write_reg(uint8_t reg_addr, uint16_t reg_data);
int sensor_write_reg(uint16_t reg_addr, uint16_t reg_data);
// Set the sensor pixel format.
int sensor_set_pixformat(pixformat_t pixformat);