xiuos/Ubiquitous/RT_Thread/drivers/ov2640/ov2640_source/drv_ov2640.c

1748 lines
39 KiB
C

/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-08-03 thread-liu the first version
* 2021-1-15 xiaoyu add set resolution function and the way of reset different manufactures's ov2640 egg:zhendianyuanzi and weixue
*/
#include "board.h"
#include <rtthread.h>
#include <stdlib.h>
#ifdef DRV_USING_OV2640
#include <drv_ov2640.h>
#ifdef RT_USING_POSIX
#include <dfs_posix.h>
#include <dfs_poll.h>
#ifdef RT_USING_POSIX_TERMIOS
#include <posix_termios.h>
#endif
#endif
#define DRV_DEBUG
#define LOG_TAG "drv.ov2640"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
/*
resolution grade:
160,120, //QQVGA 0
176,144, //QCIF 1
320,240, //QVGA 2
400,240, //WQVGA 3
352,288, //CIF 4
640,480, //VGA 5
800,600, //SVGA 6
1024,768, //XGA 7
1280,800, //WXGA 8
1280,960, //XVGA 9
1440,900, //WXGA+ 10
1280,1024, //SXGA 11
1600,1200, //UXGA 12
*/
#ifdef SOC_FAMILY_STM32
static rt_uint8_t g_ov2640_reso_level = 6; //resolution level variable 0 ~ 12
#elif defined BOARD_K210_EVB
static rt_uint8_t g_ov2640_reso_level = 2;
#endif
static struct camera_device _ov2640_device;
const rt_uint8_t OV2640_AUTOEXPOSURE_LEVEL[5][8]=
{
{
0xFF,0x01,
0x24,0x20,
0x25,0x18,
0x26,0x60,
},
{
0xFF,0x01,
0x24,0x34,
0x25,0x1c,
0x26,0x00,
},
{
0xFF,0x01,
0x24,0x3e,
0x25,0x38,
0x26,0x81,
},
{
0xFF,0x01,
0x24,0x48,
0x25,0x40,
0x26,0x81,
},
{
0xFF,0x01,
0x24,0x58,
0x25,0x50,
0x26,0x92,
},
};
//SXGA(1600*1200)
#ifdef OV2640_ZDYZ
const rt_uint8_t ov2640_sxga_init_reg_tbl[][2]=
{
0xff, 0x00,
0x2c, 0xff,
0x2e, 0xdf,
0xff, 0x01,
0x3c, 0x32,
//
0x11, 0x00,
0x09, 0x02,
0x04, 0xD8,
0x13, 0xe5,
0x14, 0x48,
0x2c, 0x0c,
0x33, 0x78,
0x3a, 0x33,
0x3b, 0xfB,
//
0x3e, 0x00,
0x43, 0x11,
0x16, 0x10,
//
0x39, 0x92,
//
0x35, 0xda,
0x22, 0x1a,
0x37, 0xc3,
0x23, 0x00,
0x34, 0xc0,
0x36, 0x1a,
0x06, 0x88,
0x07, 0xc0,
0x0d, 0x87,
0x0e, 0x41,
0x4c, 0x00,
0x48, 0x00,
0x5B, 0x00,
0x42, 0x03,
//
0x4a, 0x81,
0x21, 0x99,
//
0x24, 0x40,
0x25, 0x38,
0x26, 0x82,
0x5c, 0x00,
0x63, 0x00,
0x46, 0x00,
0x0c, 0x3c,
//
0x61, 0x70,
0x62, 0x80,
0x7c, 0x05,
//
0x20, 0x80,
0x28, 0x30,
0x6c, 0x00,
0x6d, 0x80,
0x6e, 0x00,
0x70, 0x02,
0x71, 0x94,
0x73, 0xc1,
0x3d, 0x34,
0x5a, 0x57,
//
0x12, 0x00,//UXGA 1600*1200
0x17, 0x11,
0x18, 0x75,
0x19, 0x01,
0x1a, 0x97,
0x32, 0x36,
0x03, 0x0f,
0x37, 0x40,
//
0x4f, 0xca,
0x50, 0xa8,
0x5a, 0x23,
0x6d, 0x00,
0x6d, 0x38,
//
0xff, 0x00,
0xe5, 0x7f,
0xf9, 0xc0,
0x41, 0x24,
0xe0, 0x14,
0x76, 0xff,
0x33, 0xa0,
0x42, 0x20,
0x43, 0x18,
0x4c, 0x00,
0x87, 0xd5,
0x88, 0x3f,
0xd7, 0x03,
0xd9, 0x10,
0xd3, 0x82,
//
0xc8, 0x08,
0xc9, 0x80,
//
0x7c, 0x00,
0x7d, 0x00,
0x7c, 0x03,
0x7d, 0x48,
0x7d, 0x48,
0x7c, 0x08,
0x7d, 0x20,
0x7d, 0x10,
0x7d, 0x0e,
//
0x90, 0x00,
0x91, 0x0e,
0x91, 0x1a,
0x91, 0x31,
0x91, 0x5a,
0x91, 0x69,
0x91, 0x75,
0x91, 0x7e,
0x91, 0x88,
0x91, 0x8f,
0x91, 0x96,
0x91, 0xa3,
0x91, 0xaf,
0x91, 0xc4,
0x91, 0xd7,
0x91, 0xe8,
0x91, 0x20,
//
0x92, 0x00,
0x93, 0x06,
0x93, 0xe3,
0x93, 0x05,
0x93, 0x05,
0x93, 0x00,
0x93, 0x04,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
//
0x96, 0x00,
0x97, 0x08,
0x97, 0x19,
0x97, 0x02,
0x97, 0x0c,
0x97, 0x24,
0x97, 0x30,
0x97, 0x28,
0x97, 0x26,
0x97, 0x02,
0x97, 0x98,
0x97, 0x80,
0x97, 0x00,
0x97, 0x00,
//
0xc3, 0xef,
0xa4, 0x00,
0xa8, 0x00,
0xc5, 0x11,
0xc6, 0x51,
0xbf, 0x80,
0xc7, 0x10,
0xb6, 0x66,
0xb8, 0xA5,
0xb7, 0x64,
0xb9, 0x7C,
0xb3, 0xaf,
0xb4, 0x97,
0xb5, 0xFF,
0xb0, 0xC5,
0xb1, 0x94,
0xb2, 0x0f,
0xc4, 0x5c,
//
0xc0, 0xc8,
0xc1, 0x96,
0x8c, 0x00,
0x86, 0x3d,
0x50, 0x00,
0x51, 0x90,
0x52, 0x2c,
0x53, 0x00,
0x54, 0x00,
0x55, 0x88,
0x5a, 0x90,
0x5b, 0x2C,
0x5c, 0x05,
0xd3, 0x04,//auto xiaoxin
//
0xc3, 0xed,
0x7f, 0x00,
0xda, 0x09,
0xe5, 0x1f,
0xe1, 0x67,
0xe0, 0x00,
0xdd, 0x7f,
0x05, 0x00,
};
#else
const rt_uint8_t ov2640_sxga_init_reg_tbl[][2]=
{
{0xff, 0x00},
{0x2c, 0xff},
{0x2e, 0xdf},
{0xff, 0x01},
{0x3c, 0x32},
{0x11, 0x00},
{0x09, 0x02},
{0x04, 0xD8},
{0x13, 0xe5},
{0x14, 0x48},
{0x2c, 0x0c},
{0x33, 0x78},
{0x3a, 0x33},
{0x3b, 0xfB},
{0x3e, 0x00},
{0x43, 0x11},
{0x16, 0x10},
{0x39, 0x92},
{0x35, 0xda},
{0x22, 0x1a},
{0x37, 0xc3},
{0x23, 0x00},
{0x34, 0xc0},
{0x36, 0x1a},
{0x06, 0x88},
{0x07, 0xc0},
{0x0d, 0x87},
{0x0e, 0x41},
{0x4c, 0x00},
{0x48, 0x00},
{0x5B, 0x00},
{0x42, 0x03},
{0x4a, 0x81},
{0x21, 0x99},
{0x24, 0x40},
{0x25, 0x38},
{0x26, 0x82},
{0x5c, 0x00},
{0x63, 0x00},
{0x46, 0x00},
{0x0c, 0x3c},
{0x61, 0x70},
{0x62, 0x80},
{0x7c, 0x05},
{0x20, 0x80},
{0x28, 0x30},
{0x6c, 0x00},
{0x6d, 0x80},
{0x6e, 0x00},
{0x70, 0x02},
{0x71, 0x94},
{0x73, 0xc1},
{0x3d, 0x34},
{0x5a, 0x57},
{0x12, 0x00},
{0x17, 0x11},
{0x18, 0x75},
{0x19, 0x01},
{0x1a, 0x97},
{0x32, 0x36},
{0x03, 0x0f},
{0x37, 0x40},
{0x4f, 0xca},
{0x50, 0xa8},
{0x5a, 0x23},
{0x6d, 0x00},
{0x6d, 0x38},
{0xff, 0x00},
{0xe5, 0x7f},
{0xf9, 0xc0},
{0x41, 0x24},
{0xe0, 0x14},
{0x76, 0xff},
{0x33, 0xa0},
{0x42, 0x20},
{0x43, 0x18},
{0x4c, 0x00},
{0x87, 0xd5},
{0x88, 0x3f},
{0xd7, 0x03},
{0xd9, 0x10},
{0xd3, 0x82},
{0xc8, 0x08},
{0xc9, 0x80},
{0x7c, 0x00},
{0x7d, 0x00},
{0x7c, 0x03},
{0x7d, 0x48},
{0x7d, 0x48},
{0x7c, 0x08},
{0x7d, 0x20},
{0x7d, 0x10},
{0x7d, 0x0e},
{0x90, 0x00},
{0x91, 0x0e},
{0x91, 0x1a},
{0x91, 0x31},
{0x91, 0x5a},
{0x91, 0x69},
{0x91, 0x75},
{0x91, 0x7e},
{0x91, 0x88},
{0x91, 0x8f},
{0x91, 0x96},
{0x91, 0xa3},
{0x91, 0xaf},
{0x91, 0xc4},
{0x91, 0xd7},
{0x91, 0xe8},
{0x91, 0x20},
{0x92, 0x00},
{0x93, 0x06},
{0x93, 0xe3},
{0x93, 0x05},
{0x93, 0x05},
{0x93, 0x00},
{0x93, 0x04},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x96, 0x00},
{0x97, 0x08},
{0x97, 0x19},
{0x97, 0x02},
{0x97, 0x0c},
{0x97, 0x24},
{0x97, 0x30},
{0x97, 0x28},
{0x97, 0x26},
{0x97, 0x02},
{0x97, 0x98},
{0x97, 0x80},
{0x97, 0x00},
{0x97, 0x00},
{0xc3, 0xef},
{0xa4, 0x00},
{0xa8, 0x00},
{0xc5, 0x11},
{0xc6, 0x51},
{0xbf, 0x80},
{0xc7, 0x10},
{0xb6, 0x66},
{0xb8, 0xA5},
{0xb7, 0x64},
{0xb9, 0x7C},
{0xb3, 0xaf},
{0xb4, 0x97},
{0xb5, 0xFF},
{0xb0, 0xC5},
{0xb1, 0x94},
{0xb2, 0x0f},
{0xc4, 0x5c},
{0xc0, 0xc8},
{0xc1, 0x96},
{0x8c, 0x00},
{0x86, 0x3d},
{0x50, 0x00},
{0x51, 0x90},
{0x52, 0x2c},
{0x53, 0x00},
{0x54, 0x00},
{0x55, 0x88},
{0x5a, 0x90},
{0x5b, 0x2C},
{0x5c, 0x05},
{0xd3, 0x02},
{0xc3, 0xed},
{0x7f, 0x00},
{0xda, 0x09},
{0xe5, 0x1f},
{0xe1, 0x67},
{0xe0, 0x00},
{0xdd, 0x7f},
{0x05, 0x00},
};
#endif
/* SVGA 800*600 */
const rt_uint8_t ov2640_svga_init_reg_tbl[][2]=
{
{0xff, 0x00},
{0x2c, 0xff},
{0x2e, 0xdf},
{0xff, 0x01},
{0x3c, 0x32},
{0x11, 0x00},
{0x09, 0x02},
{0x04, 0xD8},
{0x13, 0xe5},
{0x14, 0x48},
{0x2c, 0x0c},
{0x33, 0x78},
{0x3a, 0x33},
{0x3b, 0xfB},
{0x3e, 0x00},
{0x43, 0x11},
{0x16, 0x10},
{0x39, 0x92},
{0x35, 0xda},
{0x22, 0x1a},
{0x37, 0xc3},
{0x23, 0x00},
{0x34, 0xc0},
{0x36, 0x1a},
{0x06, 0x88},
{0x07, 0xc0},
{0x0d, 0x87},
{0x0e, 0x41},
{0x4c, 0x00},
{0x48, 0x00},
{0x5B, 0x00},
{0x42, 0x03},
{0x4a, 0x81},
{0x21, 0x99},
{0x24, 0x40},
{0x25, 0x38},
{0x26, 0x82},
{0x5c, 0x00},
{0x63, 0x00},
{0x46, 0x22},
{0x0c, 0x3c},
{0x61, 0x70},
{0x62, 0x80},
{0x7c, 0x05},
{0x20, 0x80},
{0x28, 0x30},
{0x6c, 0x00},
{0x6d, 0x80},
{0x6e, 0x00},
{0x70, 0x02},
{0x71, 0x94},
{0x73, 0xc1},
{0x3d, 0x34},
{0x5a, 0x57},
{0x12, 0x40},
{0x17, 0x11},
{0x18, 0x43},
{0x19, 0x00},
{0x1a, 0x4b},
{0x32, 0x09},
{0x37, 0xc0},
{0x4f, 0xca},
{0x50, 0xa8},
{0x5a, 0x23},
{0x6d, 0x00},
{0x3d, 0x38},
{0xff, 0x00},
{0xe5, 0x7f},
{0xf9, 0xc0},
{0x41, 0x24},
{0xe0, 0x14},
{0x76, 0xff},
{0x33, 0xa0},
{0x42, 0x20},
{0x43, 0x18},
{0x4c, 0x00},
{0x87, 0xd5},
{0x88, 0x3f},
{0xd7, 0x03},
{0xd9, 0x10},
{0xd3, 0x82},
{0xc8, 0x08},
{0xc9, 0x80},
{0x7c, 0x00},
{0x7d, 0x00},
{0x7c, 0x03},
{0x7d, 0x48},
{0x7d, 0x48},
{0x7c, 0x08},
{0x7d, 0x20},
{0x7d, 0x10},
{0x7d, 0x0e},
{0x90, 0x00},
{0x91, 0x0e},
{0x91, 0x1a},
{0x91, 0x31},
{0x91, 0x5a},
{0x91, 0x69},
{0x91, 0x75},
{0x91, 0x7e},
{0x91, 0x88},
{0x91, 0x8f},
{0x91, 0x96},
{0x91, 0xa3},
{0x91, 0xaf},
{0x91, 0xc4},
{0x91, 0xd7},
{0x91, 0xe8},
{0x91, 0x20},
{0x92, 0x00},
{0x93, 0x06},
{0x93, 0xe3},
{0x93, 0x05},
{0x93, 0x05},
{0x93, 0x00},
{0x93, 0x04},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x93, 0x00},
{0x96, 0x00},
{0x97, 0x08},
{0x97, 0x19},
{0x97, 0x02},
{0x97, 0x0c},
{0x97, 0x24},
{0x97, 0x30},
{0x97, 0x28},
{0x97, 0x26},
{0x97, 0x02},
{0x97, 0x98},
{0x97, 0x80},
{0x97, 0x00},
{0x97, 0x00},
{0xc3, 0xed},
{0xa4, 0x00},
{0xa8, 0x00},
{0xc5, 0x11},
{0xc6, 0x51},
{0xbf, 0x80},
{0xc7, 0x10},
{0xb6, 0x66},
{0xb8, 0xA5},
{0xb7, 0x64},
{0xb9, 0x7C},
{0xb3, 0xaf},
{0xb4, 0x97},
{0xb5, 0xFF},
{0xb0, 0xC5},
{0xb1, 0x94},
{0xb2, 0x0f},
{0xc4, 0x5c},
{0xc0, 0x64},
{0xc1, 0x4B},
{0x8c, 0x00},
{0x86, 0x3D},
{0x50, 0x00},
{0x51, 0xC8},
{0x52, 0x96},
{0x53, 0x00},
{0x54, 0x00},
{0x55, 0x00},
{0x5a, 0xC8},
{0x5b, 0x96},
{0x5c, 0x00},
{0xd3, 0x02},
{0xc3, 0xed},
{0x7f, 0x00},
{0xda, 0x09},
{0xe5, 0x1f},
{0xe1, 0x67},
{0xe0, 0x00},
{0xdd, 0x7f},
{0x05, 0x00},
};
const rt_uint8_t ov2640_jpeg_reg_tbl[][2]=
{
{0xff, 0x01},
{0xe0, 0x14},
{0xe1, 0x77},
{0xe5, 0x1f},
{0xd7, 0x03},
{0xda, 0x10},
{0xe0, 0x00},
};
const rt_uint8_t ov2640_rgb565_reg_tbl[][2]=
{
{0xFF, 0x00},
{0xDA, 0x08},
{0xD7, 0x03},
{0xDF, 0x02},
{0x33, 0xa0},
{0x3C, 0x00},
{0xe1, 0x67},
{0xff, 0x01},
{0xe0, 0x00},
{0xe1, 0x00},
{0xe5, 0x00},
{0xd7, 0x00},
{0xda, 0x00},
{0xe0, 0x00},
};
const rt_uint8_t ov2640_yuv422_reg_tbl[][2] =
{
{0xFF, 0x00},
{0xDA, 0x10},
{0xD7, 0x03},
{0xDF, 0x00},
{0x33, 0x80},
{0x3C, 0x40},
{0xe1, 0x77},
{0x00, 0x00},
};
const rt_uint16_t jpeg_img_size_tbl[][2]=
{
160,120, //QQVGA 0
176,144, //QCIF 1
320,240, //QVGA 2
400,240, //WQVGA 3
352,288, //CIF 4
640,480, //VGA 5
800,600, //SVGA 6
1024,768, //XGA 7
1280,800, //WXGA 8
1280,960, //XVGA 9
1440,900, //WXGA+ 10
1280,1024, //SXGA 11
1600,1200, //UXGA 12
};
struct rt_i2c_bus_device *i2c_bus = RT_NULL;
/* event control block*/
static struct rt_event g_rec_photo_event;
/*ov2640 mutex */
static rt_mutex_t g_ov2640_mutex = RT_NULL;
static rt_err_t sccb_read_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *buf)
{
if(NULL == buf)
{
LOG_E("buf == NULL");
return RT_ERROR;
}
#ifdef SOC_FAMILY_STM32
//stm32 bsp
struct rt_i2c_msg msg[2];
RT_ASSERT(bus != RT_NULL);
msg[0].addr = DEV_ADDRESS;
msg[0].flags = RT_I2C_WR;
msg[0].buf = &reg;
msg[0].len = 2;
msg[1].addr = DEV_ADDRESS;
msg[1].flags = RT_I2C_RD;
msg[1].len = 1;
msg[1].buf = buf;
if (rt_i2c_transfer(bus, msg, 2) == 2)
{
return RT_EOK;
}
return RT_ERROR;
#elif defined BOARD_K210_EVB
//k210 bsp
*buf =dvp_sccb_receive_data(DEV_ADDRESS,reg);
return RT_EOK;
#endif
}
/* i2c write reg */
static rt_err_t sccb_write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data)
{
#ifdef SOC_FAMILY_STM32
rt_uint8_t buf[2];
struct rt_i2c_msg msgs;
RT_ASSERT(bus != RT_NULL);
buf[0] = reg ;
buf[1] = data;
msgs.addr = DEV_ADDRESS;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = 2;
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
return RT_ERROR;
#elif defined BOARD_K210_EVB
dvp_sccb_send_data(DEV_ADDRESS,reg,data);
return RT_EOK;
#endif
}
static rt_err_t ov2640_read_id(struct rt_i2c_bus_device *bus)
{
rt_uint8_t read_value[2];
rt_uint16_t id = 0;
sccb_read_reg(bus, OV2640_SENSOR_MIDH,&read_value[0]);
sccb_read_reg(bus, OV2640_SENSOR_MIDL,&read_value[1]);
id = ((rt_uint16_t)(read_value[0] << 8) & 0xFF00);
id |= ((rt_uint16_t)(read_value[1]) & 0x00FF);
if (id != OV2640_MID)
{
LOG_E("ov2640 init error, mid: 0x%x ", id);
return RT_ERROR;
}
LOG_I("ov2640 read mid success, mid: 0x%x ", id);
sccb_read_reg(bus, OV2640_SENSOR_PIDH, &read_value[0]);
sccb_read_reg(bus, OV2640_SENSOR_PIDL, &read_value[1]);
id = ((rt_uint16_t)(read_value[0] << 8) & 0xFF00);
id |= ((rt_uint16_t)(read_value[1]) & 0x00FF);
if (id != OV2640_PID)
{
LOG_E("ov2640 init error, pid: 0x%04x ", id);
return RT_ERROR;
}
LOG_I("ov2640 read hid success, pid: 0x%04x", id);
return RT_EOK;
}
/* change ov2640 to jpeg mode */
void ov2640_jpeg_mode(void)
{
rt_uint16_t i=0;
/* set yun422 mode */
for (i = 0; i < (sizeof(ov2640_yuv422_reg_tbl) / 2); i++)
{
sccb_write_reg(i2c_bus, ov2640_yuv422_reg_tbl[i][0],ov2640_yuv422_reg_tbl[i][1]);
}
/* set jpeg mode */
for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++)
{
sccb_write_reg(i2c_bus, ov2640_jpeg_reg_tbl[i][0],ov2640_jpeg_reg_tbl[i][1]);
}
}
/* change ov2640 to rgb565 mode */
void ov2640_rgb565_mode(void)
{
rt_uint16_t i=0;
for (i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++)
{
sccb_write_reg(i2c_bus, ov2640_rgb565_reg_tbl[i][0],ov2640_rgb565_reg_tbl[i][1]);
}
}
/* set auto exposure level value must be 0 ~4 */
void ov2640_set_auto_exposure(rt_uint8_t level)
{
rt_uint8_t i = 0;
rt_uint8_t *p = (rt_uint8_t*)OV2640_AUTOEXPOSURE_LEVEL[level];
for (i = 0; i < 4; i++)
{
sccb_write_reg(i2c_bus, p[i*2],p[i*2+1]);
}
}
/* set light mode
* 0: auto
* 1: sunny
* 2: cloudy
* 3: office
* 4: home
* */
void ov2640_set_light_mode(rt_uint8_t mode)
{
rt_uint8_t regccval, regcdval, regceval;
switch(mode)
{
case 0:
sccb_write_reg(i2c_bus, 0xFF, 0x00);
sccb_write_reg(i2c_bus, 0xC7, 0x10);
return;
case 2:
regccval = 0x65;
regcdval = 0x41;
regceval = 0x4F;
break;
case 3:
regccval = 0x52;
regcdval = 0x41;
regceval = 0x66;
break;
case 4:
regccval = 0x42;
regcdval = 0x3F;
regceval = 0x71;
break;
default:
regccval = 0x5E;
regcdval = 0x41;
regceval = 0x54;
break;
}
sccb_write_reg(i2c_bus, 0xFF, 0x00);
sccb_write_reg(i2c_bus, 0xC7, 0x40);
sccb_write_reg(i2c_bus, 0xCC, regccval);
sccb_write_reg(i2c_bus, 0xCD, regcdval);
sccb_write_reg(i2c_bus, 0xCE, regceval);
}
/* set color saturation
* 0: -2
* 1: -1
* 2: 0
* 3: +1
* 4: +2
* */
void ov2640_set_color_saturation(rt_uint8_t sat)
{
rt_uint8_t reg7dval = ((sat+2)<<4) | 0x08;
sccb_write_reg(i2c_bus, 0xFF, 0X00);
sccb_write_reg(i2c_bus, 0x7C, 0X00);
sccb_write_reg(i2c_bus, 0x7D, 0X02);
sccb_write_reg(i2c_bus, 0x7C, 0X03);
sccb_write_reg(i2c_bus, 0x7D, reg7dval);
sccb_write_reg(i2c_bus, 0x7D, reg7dval);
}
/* set brightness
* 0: -2
* 1: -1
* 2: 0
* 3: 1
* 4: 2
* */
void ov2640_set_brightness(rt_uint8_t bright)
{
sccb_write_reg(i2c_bus, 0xff, 0x00);
sccb_write_reg(i2c_bus, 0x7c, 0x00);
sccb_write_reg(i2c_bus, 0x7d, 0x04);
sccb_write_reg(i2c_bus, 0x7c, 0x09);
sccb_write_reg(i2c_bus, 0x7d, bright << 4);
sccb_write_reg(i2c_bus, 0x7d, 0x00);
}
/* set contrast
* 0: -2
* 1: -1
* 2: 0
* 3: 1
* 4: 2
* */
void ov2640_set_contrast(rt_uint8_t contrast)
{
rt_uint8_t reg7d0val, reg7d1val;
switch(contrast)
{
case 0:
reg7d0val = 0x18;
reg7d1val = 0x34;
break;
case 1:
reg7d0val = 0x1C;
reg7d1val = 0x2A;
break;
case 3:
reg7d0val = 0x24;
reg7d1val = 0x16;
break;
case 4:
reg7d0val = 0x28;
reg7d1val = 0x0C;
break;
default:
reg7d0val = 0x20;
reg7d1val = 0x20;
break;
}
sccb_write_reg(i2c_bus, 0xff, 0x00);
sccb_write_reg(i2c_bus, 0x7c, 0x00);
sccb_write_reg(i2c_bus, 0x7d, 0x04);
sccb_write_reg(i2c_bus, 0x7c, 0x07);
sccb_write_reg(i2c_bus, 0x7d, 0x20);
sccb_write_reg(i2c_bus, 0x7d, reg7d0val);
sccb_write_reg(i2c_bus, 0x7d, reg7d1val);
sccb_write_reg(i2c_bus, 0x7d, 0x06);
}
/* set special effects
* 0: noraml
* 1: negative film
* 2: black-and-white
* 3: the red
* 4: the green
* 5: the blue
* 6: Retro
*/
void ov2640_set_special_effects(rt_uint8_t eft)
{
rt_uint8_t reg7d0val, reg7d1val, reg7d2val;
switch(eft)
{
case 1:
reg7d0val = 0x40;
break;
case 2:
reg7d0val = 0x18;
break;
case 3:
reg7d0val = 0x18;
reg7d1val = 0x40;
reg7d2val = 0xC0;
break;
case 4:
reg7d0val = 0x18;
reg7d1val = 0x40;
reg7d2val = 0x40;
break;
case 5:
reg7d0val = 0x18;
reg7d1val = 0xA0;
reg7d2val = 0x40;
break;
case 6:
reg7d0val = 0x18;
reg7d1val = 0x40;
reg7d2val = 0xA6;
break;
default:
reg7d0val = 0x00;
reg7d1val = 0x80;
reg7d2val = 0x80;
break;
}
sccb_write_reg(i2c_bus, 0xff, 0x00);
sccb_write_reg(i2c_bus, 0x7c, 0x00);
sccb_write_reg(i2c_bus, 0x7d, reg7d0val);
sccb_write_reg(i2c_bus, 0x7c, 0x05);
sccb_write_reg(i2c_bus, 0x7d, reg7d1val);
sccb_write_reg(i2c_bus, 0x7d, reg7d2val);
}
/* set the image output window */
void ov2640_set_window_size(rt_uint16_t sx,rt_uint16_t sy,rt_uint16_t width,rt_uint16_t height)
{
rt_uint16_t endx;
rt_uint16_t endy;
rt_uint8_t temp;
endx = sx + width / 2;
endy = sy + height / 2;
sccb_write_reg(i2c_bus, 0xFF, 0x01);
sccb_read_reg(i2c_bus, 0x03, &temp);
temp &= 0xF0;
temp |= ((endy & 0x03) << 2) | (sy & 0x03);
sccb_write_reg(i2c_bus, 0x03, temp);
sccb_write_reg(i2c_bus, 0x19, sy>>2);
sccb_write_reg(i2c_bus, 0x1A, endy>>2);
sccb_read_reg(i2c_bus, 0x32, &temp);
temp &= 0xC0;
temp |= ((endx & 0x07) << 3) | (sx & 0x07);
sccb_write_reg(i2c_bus, 0x32, temp);
sccb_write_reg(i2c_bus, 0x17, sx>>3);
sccb_write_reg(i2c_bus, 0x18, endx>>3);
}
/* set the image output size */
rt_uint8_t ov2640_set_image_out_size(rt_uint16_t width,rt_uint16_t height)
{
rt_uint16_t outh, outw;
rt_uint8_t temp;
if(width%4)return 1;
if(height%4)return 2;
outw = width /4;
outh = height/4;
sccb_write_reg(i2c_bus, 0xFF, 0x00);
sccb_write_reg(i2c_bus, 0xE0, 0x04);
sccb_write_reg(i2c_bus, 0x5A, outw & 0XFF);
sccb_write_reg(i2c_bus, 0x5B, outh & 0XFF);
temp = (outw >> 8) & 0x03;
temp |= (outh >> 6) & 0x04;
sccb_write_reg(i2c_bus, 0x5C, temp);
sccb_write_reg(i2c_bus, 0xE0, 0X00);
return RT_EOK;
}
/* set the image window size */
rt_uint8_t ov2640_set_image_window_size(rt_uint16_t offx, rt_uint16_t offy, rt_uint16_t width, rt_uint16_t height)
{
rt_uint16_t hsize, vsize;
rt_uint8_t temp;
if ((width % 4) || (height%4))
{
return RT_ERROR;
}
hsize = width /4;
vsize = height/4;
sccb_write_reg(i2c_bus, 0XFF,0X00);
sccb_write_reg(i2c_bus, 0XE0,0X04);
sccb_write_reg(i2c_bus, 0X51,hsize&0XFF);
sccb_write_reg(i2c_bus, 0X52,vsize&0XFF);
sccb_write_reg(i2c_bus, 0X53,offx&0XFF);
sccb_write_reg(i2c_bus, 0X54,offy&0XFF);
temp=(vsize>>1)&0X80;
temp|=(offy>>4)&0X70;
temp|=(hsize>>5)&0X08;
temp|=(offx>>8)&0X07;
sccb_write_reg(i2c_bus, 0X55,temp); //
sccb_write_reg(i2c_bus, 0X57,(hsize>>2)&0X80); //
sccb_write_reg(i2c_bus, 0XE0,0X00);
return 0;
}
/* set output resolution */
rt_uint8_t ov2640_set_image_size(rt_uint16_t width ,rt_uint16_t height)
{
rt_uint8_t temp;
sccb_write_reg(i2c_bus, 0xFF, 0x00);
sccb_write_reg(i2c_bus, 0xE0, 0x04);
sccb_write_reg(i2c_bus, 0xC0, (width >>3) & 0xFF);
sccb_write_reg(i2c_bus, 0xC1, (height >> 3) & 0xFF);
temp = (width & 0x07) << 3;
temp |= height & 0x07;
temp |= (width >> 4) & 0x80;
sccb_write_reg(i2c_bus, 0x8C, temp);
sccb_write_reg(i2c_bus, 0xE0, 0x00);
return RT_EOK;
}
int rt_ov2640_readid_test()
{
#ifdef SOC_FAMILY_STM32
i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
if (i2c_bus == RT_NULL)
{
LOG_E("can't find %c deivce", I2C_NAME);
return RT_ERROR;
}
#endif
sccb_write_reg(i2c_bus, OV2640_DSP_RA_DLMT, 0x01);
rt_thread_delay(10);
sccb_write_reg(i2c_bus, OV2640_SENSOR_COM7, 0x80);
ov2640_read_id(i2c_bus);
return RT_EOK;
}
rt_uint32_t rt_ov2640_calculate_jpeg_len(rt_uint8_t* pdata,rt_uint32_t maxlength)
{
rt_uint32_t length = 0;
if((*pdata != 0xFF)&&(*(pdata+1) != 0xD8))
{
LOG_E("the data is error this time ");
return 0;
}
for(;length<maxlength;length++)
{
if((*(pdata+length)== 0xFF)&&(*(pdata+length+1) == 0xD9))
{
return length+1+1;
}
}
LOG_E("the data tail is error this time ");
return 0;
}
#ifdef SOC_FAMILY_STM32
/*
Different hardware circuits have different reset modes
*/
#ifdef OV2640_ZDYZ
void rt_stm32407_atk_miniexpolre()
{
/*
no pull-up resistance
*/
GPIO_InitTypeDef GPIO_Initure = {0};
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE(); //
GPIO_Initure.Pin=GPIO_PIN_6;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_7;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_OD;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_9|GPIO_PIN_15;//PG9,15 PG9---->PWDN PG15------>RST
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOG,&GPIO_Initure);
rt_thread_mdelay(10);
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_RESET);
rt_thread_mdelay(10);
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_15,GPIO_PIN_RESET);
rt_thread_mdelay(10);
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_15,GPIO_PIN_SET);
}
#else
void rt_ov2460_rcc_int(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_1);
}
#endif
#endif
void ov2640_set_resolution(int value)
{
int i = 0;
if(value < 0 || value >13)
{
LOG_E("resolution parameter is error!");
return;
}
if(13 == value)
{
LOG_I("set image :");
LOG_I(" 160,120, QQVGA 0 ");
LOG_I(" 176,144, QCIF 1 ");
LOG_I(" 320,240, QVGA 2" );
LOG_I(" 400,240, WQVGA 3 ");
LOG_I(" 352,288, CIF 4" );
LOG_I(" 640,480, VGA 5 ");
LOG_I(" 800,600, SVGA 6");
LOG_I(" 1024,768, XGA 7 ");
LOG_I(" 1280,800, WXGA 8 ");
LOG_I(" 1280,960, XVGA 9 ");
LOG_I(" 1440,900, WXGA+ 10");
LOG_I(" 1280,1024, SXGA 11");
LOG_I(" 1280,1024, UXGA 12");
return;
}
g_ov2640_reso_level = value;
#ifdef SOC_FAMILY_STM32
#ifdef OV2640_ZDYZ
rt_stm32407_atk_miniexpolre();
#else
/*
At present, the design of RST reset pin is not carried out by Micro Snow Electronics,
which can be added later. Therefore, there will be problems if the micro snow electronic setting is connected here
*/
rt_ov2460_rcc_int();
#endif
#endif
sccb_write_reg(i2c_bus, OV2640_DSP_RA_DLMT, 0x01);
sccb_write_reg(i2c_bus, OV2640_SENSOR_COM7, 0x80);
ov2640_read_id(i2c_bus);
if(g_ov2640_reso_level > LARGE_PHOTO_MODE)
{
for (i = 0; i < sizeof(ov2640_sxga_init_reg_tbl) / 2; i++)
{
sccb_write_reg(i2c_bus, ov2640_sxga_init_reg_tbl[i][0], ov2640_sxga_init_reg_tbl[i][1]);
}
LOG_I("out put big picture mode ");
}
else
{
for (i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++)
{
sccb_write_reg(i2c_bus, ov2640_svga_init_reg_tbl[i][0], ov2640_svga_init_reg_tbl[i][1]);
}
LOG_I("out put small picture mode ");
}
ov2640_rgb565_mode();
ov2640_jpeg_mode();
ov2640_set_image_window_size(0, 0, jpeg_img_size_tbl[g_ov2640_reso_level ][0],jpeg_img_size_tbl[g_ov2640_reso_level ][1]);
ov2640_set_image_out_size(jpeg_img_size_tbl[g_ov2640_reso_level ][0], jpeg_img_size_tbl[g_ov2640_reso_level ][1]);
LOG_I("set image resolution is %d * %d success\n\r",jpeg_img_size_tbl[g_ov2640_reso_level ][0],jpeg_img_size_tbl[g_ov2640_reso_level ][1]);
}
/*
set ov2640 configuration function
*/
void set_ov2640_config(int argc, char **argv)
{
rt_int8_t cmd = 0;
rt_int16_t value = 0;
LOG_I("set ov2640 configuration :");
if(argc < 2)
{
LOG_E("Usage: set_ov2640_config grade");
LOG_E("like: set_ov2640_config 25(CMD) 2(value) (cmd 25 (color saturation) value is 2 (0~4)");
return;
}
if(NULL != strstr(argv[1],"help"))
{
LOG_I(" set_ov2640_config CMD value");
#ifdef SOC_FAMILY_STM32
LOG_I(" CMD 23 is setting resolution,value should be 0~12(0-12 is resolution level value 13 display particulars)");
#endif
LOG_I(" CMD 24 is setting light mode,value should be 0~4(0: auto 1: sunny,2: cloudy,3: office,4:home)");
LOG_I(" CMD 25 is setting color saturation,value should be 0~4(0: -2 1:-1,2:0,3:1,4: 2)");
LOG_I(" CMD 26 is setting brightness,value should be 0~4(0: -2 1:-1,2:0,3:1,4: 2)");
LOG_I(" CMD 27 is setting contrast,value should be 0~4(0: -2 1:-1,2:0,3:1,4: 2)");
LOG_I(" CMD 28 is setting effects,value should be 0~6:");
LOG_I("(0: noraml 1: negative film 2: black-and-white 3: the red 4: the green 5: the blue 6: Retro)");
LOG_I(" CMD 29 is setting exposure,value should be 0~4(0: -2 1:-1,2:0,3:1,4: 2)");
}
cmd = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 10);
LOG_I("CMD is %d vaule is %d \n",cmd,value);
if(cmd < IOCTRL_CAMERA_SET_RESO || cmd > IOCTRL_CAMERA_SET_EXPOSURE)
{
LOG_I("CMD value should be 24 ~29");
return ;
}
switch(cmd)
{
#ifdef SOC_FAMILY_STM32
case IOCTRL_CAMERA_SET_RESO:
if(value > 13 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_resolution(value);
break;
#endif
case IOCTRL_CAMERA_SET_LIGHT:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_light_mode(value);
break;
case IOCTRL_CAMERA_SET_COLOR:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_color_saturation(value);
break;
case IOCTRL_CAMERA_SET_BRIGHTNESS:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_brightness(value);
break;
case IOCTRL_CAMERA_SET_CONTRAST:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_contrast(value);
break;
case IOCTRL_CAMERA_SET_EFFECT:
if(value > 6 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_special_effects(value);
break;
case IOCTRL_CAMERA_SET_EXPOSURE:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return ;
}
ov2640_set_auto_exposure(value);
break;
default:
break;
}
}
MSH_CMD_EXPORT(set_ov2640_config,set ov2640 camera configuration);
void rt_ov2640_frame_irq_event()
{
rt_event_send(&g_rec_photo_event, RECV_EVENT_FLAG);
}
rt_err_t rt_ov2640_set_irq_hander(void (*p)(void))
{
#ifdef SOC_FAMILY_STM32
return rt_set_irq_dcmi_callback_hander(p);
#elif defined BOARD_K210_EVB
return rt_set_irq_dvp_callback_hander(p);
#endif
}
rt_err_t rt_ov2640_start_shoot(uint32_t pdata, uint32_t length)
{
rt_mutex_take(g_ov2640_mutex, RT_WAITING_FOREVER);
#ifdef SOC_FAMILY_STM32
rt_dcmi_start(pdata,length);
#elif defined BOARD_K210_EVB
rt_dvp_start(pdata,length);
#endif
if (rt_event_recv(&g_rec_photo_event, RECV_EVENT_FLAG,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
rt_tick_from_millisecond(1000*10), RT_NULL) == RT_EOK)
{
//LOG_I("receive the ov2640 data successfully.");
rt_mutex_release(g_ov2640_mutex);
return RT_EOK;
}
else
{
LOG_E("receive the ov2640 timeout(10s)");
rt_mutex_release(g_ov2640_mutex);
return RT_ERROR;
}
}
static rt_err_t rt_ov2640_open(rt_device_t dev, rt_uint16_t oflag)
{
RT_ASSERT(dev != RT_NULL);
return RT_EOK;
}
static rt_err_t rt_ov2640_close(rt_device_t dev)
{
RT_ASSERT(dev != RT_NULL);
return RT_EOK;
}
static rt_err_t rt_ov2640_control(rt_device_t dev, int cmd, void *args)
{
RT_ASSERT(dev != RT_NULL);
rt_err_t ret = RT_EOK;
if(cmd < IOCTRL_CAMERA_SET_DVP_RESO || cmd > IOCTRL_CAMERA_SET_EXPOSURE)
{
LOG_E("CMD value should be 22 ~29");
return RT_ERROR;
}
int value = 0;
_ioctl_shoot_para shoot_para = {0};
#ifdef BOARD_K210_EVB
_ioctl_set_dvp_reso set_dvp_reso = {0};
#endif
if(IOCTRL_CAMERA_START_SHOT == cmd)
{
shoot_para = *((_ioctl_shoot_para*)args);
ret = rt_ov2640_start_shoot(shoot_para.pdata,shoot_para.length);
return ret;
}
#ifdef BOARD_K210_EVB
else if(IOCTRL_CAMERA_SET_DVP_RESO == cmd)
{
set_dvp_reso =*((_ioctl_set_dvp_reso*)args);
dvp_set_image_size(set_dvp_reso.width, set_dvp_reso.height);
return RT_EOK;
}
#endif
else
{
value = *((int*)args);
switch(cmd)
{
#ifdef SOC_FAMILY_STM32
case IOCTRL_CAMERA_SET_RESO:
if(value > 13 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_resolution(value);
break;
#endif
case IOCTRL_CAMERA_SET_LIGHT:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_light_mode(value);
break;
case IOCTRL_CAMERA_SET_COLOR:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_color_saturation(value);
break;
case IOCTRL_CAMERA_SET_BRIGHTNESS:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_brightness(value);
break;
case IOCTRL_CAMERA_SET_CONTRAST:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_contrast(value);
break;
case IOCTRL_CAMERA_SET_EFFECT:
if(value > 6 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_special_effects(value);
break;
case IOCTRL_CAMERA_SET_EXPOSURE:
if(value > 4 || value < 0)
{
LOG_I("value should be 0 ~13");
return RT_EINVAL ;
}
ov2640_set_auto_exposure(value);
break;
default:
break;
}
return RT_EOK;
}
}
static rt_size_t rt_ov2640_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
RT_ASSERT(dev != RT_NULL);
return RT_EOK;
}
static rt_size_t rt_ov2640_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
RT_ASSERT(dev != RT_NULL);
return RT_EOK;
}
static rt_err_t rt_ov2640_init(rt_device_t dev)
{
RT_ASSERT(dev != RT_NULL);
rt_uint16_t i = 0;
int ret = RT_EOK;
#ifdef SOC_FAMILY_STM32
#ifdef OV2640_ZDYZ
//zheng dian yuan zi manufacture ov2640
rt_stm32407_atk_miniexpolre();
#else
//weixue manufacture ov2640
rt_ov2460_rcc_int();
#endif
i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
if (i2c_bus == RT_NULL)
{
LOG_E("can't find %c deivce", I2C_NAME);
return RT_ERROR;
}
#endif
sccb_write_reg(i2c_bus, OV2640_DSP_RA_DLMT, 0x01);
sccb_write_reg(i2c_bus, OV2640_SENSOR_COM7, 0x80);
rt_thread_mdelay(50);
ov2640_read_id(i2c_bus);
/*
set ov2640 register value
*/
if(g_ov2640_reso_level >LARGE_PHOTO_MODE )//large photo mode
{
for (i = 0; i < sizeof(ov2640_sxga_init_reg_tbl) / 2; i++)
{
sccb_write_reg(i2c_bus, ov2640_sxga_init_reg_tbl[i][0], ov2640_sxga_init_reg_tbl[i][1]);
}
}
else
{
for (i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++)
{
sccb_write_reg(i2c_bus, ov2640_svga_init_reg_tbl[i][0], ov2640_svga_init_reg_tbl[i][1]);
}
}
ov2640_rgb565_mode();
ov2640_set_light_mode(0);
ov2640_set_color_saturation(0);
ov2640_set_brightness(2);
ov2640_set_contrast(1);
#ifdef SOC_FAMILY_STM32
LOG_I("set ov2640 jpeg mode on stm32 board");
ov2640_jpeg_mode();
ov2640_set_image_window_size(0, 0, jpeg_img_size_tbl[g_ov2640_reso_level][0],jpeg_img_size_tbl[g_ov2640_reso_level][1]);
ov2640_set_image_out_size(jpeg_img_size_tbl[g_ov2640_reso_level][0], jpeg_img_size_tbl[g_ov2640_reso_level][1]);
LOG_I("set image resolution is %d * %d ",jpeg_img_size_tbl[g_ov2640_reso_level][0],jpeg_img_size_tbl[g_ov2640_reso_level][1]);
#elif defined BOARD_K210_EVB
ov2640_set_image_window_size(0, 0, jpeg_img_size_tbl[5][0],jpeg_img_size_tbl[5][1]);
ov2640_set_image_out_size(jpeg_img_size_tbl[2][0], jpeg_img_size_tbl[2][1]);
LOG_I("set ov2640 rgb565 mode on K210 board and set reselotion QVGA 320,240");
#endif
/*
initialize rt_mutex about the using of ov2640
*/
g_ov2640_mutex = rt_mutex_create("ov2640", RT_IPC_FLAG_FIFO);
if (g_ov2640_mutex == RT_NULL)
{
LOG_E("create g_ov2640_mutex mutex failed.\n");
return -RT_ERROR;
}
/*
initialize receive event object
*/
ret = rt_event_init(&g_rec_photo_event, "r_photo", RT_IPC_FLAG_FIFO);
if (RT_EOK!= ret)
{
LOG_E("init rec_photo_event failed.\n");
return -RT_ERROR;
}
/*
set dcmi or dvp interrupt callback function
*/
ret = rt_ov2640_set_irq_hander(rt_ov2640_frame_irq_event);
if(RT_EOK == ret)
{
LOG_I("ov2640 set irq hander successfully.");
}
else
{
LOG_E("ov2640 set irq hander failed");
}
return RT_EOK;
}
#ifdef RT_USING_POSIX
static int ov2640_fops_open(struct dfs_fd *fd)
{
rt_err_t ret = RT_EOK;
rt_uint16_t flags = 0;
rt_device_t device;
device = (rt_device_t)fd->data;
RT_ASSERT(device != RT_NULL);
flags = RT_DEVICE_FLAG_RDONLY;
ret = rt_device_open(device, flags);
if (ret == RT_EOK)
{
return RT_EOK;
}
return RT_ERROR;
}
static int ov2640_fops_close(struct dfs_fd *fd)
{
rt_device_t device;
device = (rt_device_t)fd->data;
rt_device_set_rx_indicate(device, RT_NULL);
rt_device_close(device);
return RT_EOK;
}
static int ov2640_fops_ioctl(struct dfs_fd *fd, int cmd, void *args)
{
rt_device_t device;
device = (rt_device_t)fd->data;
return rt_device_control(device, cmd, args);
}
const static struct dfs_file_ops ov2640_fops =
{
ov2640_fops_open,
ov2640_fops_close,
ov2640_fops_ioctl,
RT_NULL,
RT_NULL,
RT_NULL, /* flush */
RT_NULL, /* lseek */
RT_NULL, /* getdents */
RT_NULL,/*poll*/
};
#endif
int camera_ov2640_init()
{
rt_err_t ret = RT_EOK;
_ov2640_device.parent.type = RT_Device_Class_Miscellaneous;
_ov2640_device.parent.init = rt_ov2640_init;
_ov2640_device.parent.open = rt_ov2640_open;
_ov2640_device.parent.close = rt_ov2640_close;
_ov2640_device.parent.read = rt_ov2640_read;
_ov2640_device.parent.write = rt_ov2640_write;
_ov2640_device.parent.control = rt_ov2640_control;
_ov2640_device.parent.user_data = RT_NULL;
ret = rt_device_register(&_ov2640_device.parent, "ov2640", RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
#ifdef RT_USING_POSIX
_ov2640_device.parent.fops = &ov2640_fops;
#endif
if(ret != RT_EOK)
{
LOG_E("ov2640 register fail!!\n\r");
return -RT_ERROR;
}
LOG_I("ov2640 register successfully");
return RT_EOK;
}
INIT_APP_EXPORT(camera_ov2640_init);
#endif