#include "bsp_ov7725.h"
#include <rtthread.h>
#include"../libraries/ls1c_gpio.h"
#include"../libraries/ls1c_delay.h"
#include <rthw.h>
#include "mipsregs.h"
#include "ls1c.h"
#include <stdio.h>
#include "GUI.h"
#include "drv_st7735.h"
#include "suse.h"
#include "test_tft.h"
#include "hw_i2c.h"
#define WHITE 0xffff
//以下引脚定义宏为fifo所需引脚,所配置引脚位为随意配置,具体引脚等到硬件到的时候再决定
#define OE 74
#define WRST 67
#define RRST 77
#define RCLK 59
#define WE 69
#define DATA_0 76
#define DATA_1 75
#define DATA_2 58
#define DATA_3 60
#define DATA_4 62
#define DATA_5 64
#define DATA_6 66
#define DATA_7 68
#define VSYNC 28//vsync要配置成中断模式
rt_uint8_t get_data(void)
{
rt_uint8_t pic;
rt_uint8_t buf[8];
buf[0]=gpio_get(DATA_0);
buf[1]=gpio_get(DATA_1);
buf[2]=gpio_get(DATA_2);
buf[3]=gpio_get(DATA_3);
buf[4]=gpio_get(DATA_4);
buf[5]=gpio_get(DATA_5);
buf[6]=gpio_get(DATA_6);
buf[7]=gpio_get(DATA_7);
//for(pic=0;pic<8;pic++)
//{
//rt_kprintf("%d",buf[pic]);
//}
int i;
for(i=0;i<8;i++)
{
pic |= buf<<i;
}
//rt_kprintf(" ");
//rt_kprintf("pic=ox%x ",pic);
//rt_kprintf("pic=ox%d ",pic);
//rt_thread_delay(6);
return pic;
}
//摄像头初始化配置
//注意:使用这种方式初始化结构体,要在c/c++选项中选择 C99 mode
OV7725_MODE_PARAM cam_mode =
{
/*以下包含几组摄像头配置,可自行测试,保留一组,把其余配置注释掉即可*/
/************配置1*********横屏显示*****************************/
// .QVGA_VGA = 0, //QVGA模式
// .cam_sx = 0,
// .cam_sy = 0,
// .cam_width = 128,
// .cam_height = 160,
// .lcd_sx = 0,
// .lcd_sy = 0,
// .lcd_scan = 3, //LCD扫描模式,本横屏配置可用1、3、5、7模式
// //以下可根据自己的需要调整,参数范围见结构体类型定义
// .light_mode = 0,//自动光照模式
// .saturation = 0,
// .brightness = 0,
// .contrast = 0,
// .effect = 0, //正常模式
/**********配置2*********竖屏显示****************************/
/*竖屏显示需要VGA模式,同分辨率情况下,比QVGA帧率稍低*/
/*VGA模式分辨率为640*480,从中取出240*320的图像进行竖屏显示*/
/*本工程不支持超过320*240或 240*320的分辨率配置*/
.QVGA_VGA = 1, //VGA模式
//取VGA模式居中的窗口,可根据实际需要调整
.cam_sx = 0,
.cam_sy = 0,
.cam_width = 128,
.cam_height = 160, //在VGA模式下,此值才可以大于240
.lcd_sx = 0,
.lcd_sy = 0,
.lcd_scan = 0, //LCD扫描模式,本竖屏配置可用0、2、4、6模式
//以下可根据自己的需要调整,参数范围见结构体类型定义
.light_mode = 0,//自动光照模式
.saturation = 0,
.brightness = 0,
.contrast = 0,
.effect = 0, //正常模式
/*******配置3************小分辨率****************************/
/*小于320*240分辨率的,可使用QVGA模式,设置的时候注意液晶屏边界*/
// .QVGA_VGA = 0, //QVGA模式
// //取QVGA模式居中的窗口,可根据实际需要调整
// .cam_sx = 100,
// .cam_sy = 45,
// .cam_width = 128,
// .cam_height = 160,
// /*液晶屏的显示位置也可以根据需要调整,注意不要超过边界即可*/
// .lcd_sx = 50,
// .lcd_sy = 50,
// .lcd_scan = 3, //LCD扫描模式,0-7模式都支持,注意不要超过边界即可
// //以下可根据自己的需要调整,参数范围见结构体类型定义
// .light_mode = 0,//自动光照模式
// .saturation = 0,
// .brightness = 0,
// .contrast = 0,
// .effect = 0, //正常模式
};
typedef struct Reg
{
rt_uint8_t Address; /*寄存器地址*/
rt_uint8_t Value; /*寄存器值*/
}Reg_Info;
/* 寄存器参数配置 */
Reg_Info Sensor_Config[] =
{
{REG_CLKRC, 0x00}, /*clock config*/
{REG_COM7, 0x46}, /*QVGA RGB565 */
{REG_HSTART, 0x3f},
{REG_HSIZE, 0x50},
{REG_VSTRT, 0x03},
{REG_VSIZE, 0x78},
{REG_HREF, 0x00},
{REG_HOutSize, 0x50},
{REG_VOutSize, 0x78},
{REG_EXHCH, 0x00},
/*DSP control*/
{REG_TGT_B, 0x7f},
{REG_FixGain, 0x09},
{REG_AWB_Ctrl0, 0xe0},
{REG_DSP_Ctrl1, 0xff},
{REG_DSP_Ctrl2, 0x20},
{REG_DSP_Ctrl3, 0x00},
{REG_DSP_Ctrl4, 0x00},
/*AGC AEC AWB*/
{REG_COM8, 0xf0},//...........................
{REG_COM4, 0x81}, /*Pll AEC CONFIG*/
{REG_COM6, 0xc5},
{REG_COM9, 0x21},//............................
{REG_BDBase, 0xFF},
{REG_BDMStep, 0x01},
{REG_AEW, 0x34},
{REG_AEB, 0x3c},
{REG_VPT, 0xa1},
{REG_EXHCL, 0x00},
{REG_AWBCtrl3, 0xaa},
{REG_COM8, 0xff},
{REG_AWBCtrl1, 0x5d},
{REG_EDGE1, 0x0a},
{REG_DNSOff, 0x01},
{REG_EDGE2, 0x01},
{REG_EDGE3, 0x01},
{REG_MTX1, 0x5f},
{REG_MTX2, 0x53},
{REG_MTX3, 0x11},
{REG_MTX4, 0x1a},
{REG_MTX5, 0x3d},
{REG_MTX6, 0x5a},
{REG_MTX_Ctrl, 0x1e},
{REG_BRIGHT, 0x00},
{REG_CNST, 0x25},
{REG_USAT, 0x65},
{REG_VSAT, 0x65},
{REG_UVADJ0, 0x81},
//{REG_SDE, 0x20}, //黑白
{REG_SDE, 0x06}, //彩色 调节SDE这个寄存器还可以实现其他效果
/*GAMMA config*/
{REG_GAM1, 0x0c},
{REG_GAM2, 0x16},
{REG_GAM3, 0x2a},
{REG_GAM4, 0x4e},
{REG_GAM5, 0x61},
{REG_GAM6, 0x6f},
{REG_GAM7, 0x7b},
{REG_GAM8, 0x86},
{REG_GAM9, 0x8e},
{REG_GAM10, 0x97},
{REG_GAM11, 0xa4},
{REG_GAM12, 0xaf},
{REG_GAM13, 0xc5},
{REG_GAM14, 0xd7},
{REG_GAM15, 0xe8},
{REG_SLOP, 0x20},
{REG_HUECOS, 0x80},
{REG_HUESIN, 0x80},
{REG_DSPAuto, 0xff},
{REG_DM_LNL, 0x00},
{REG_BDBase, 0x99},
{REG_BDMStep, 0x03},
{REG_LC_RADI, 0x00},
{REG_LC_COEF, 0x13},
{REG_LC_XC, 0x08},
{REG_LC_COEFB, 0x14},
{REG_LC_COEFR, 0x17},
{REG_LC_CTR, 0x05},
{REG_COM3, 0xd0},/*Horizontal mirror image*/
/*night mode auto frame rate control*/
//{REG_COM5, 0xf5}, /*在夜视环境下,自动降低帧率,保证低照度画面质量*/
{REG_COM5, 0x31}, /*夜视环境帧率不变*/
};
rt_uint8_t OV7725_REG_NUM = sizeof(Sensor_Config)/sizeof(Sensor_Config[0]); /*结构体数组成员数目*/
volatile rt_uint8_t Ov7725_vsync ; /* 帧同步信号标志,在中断函数和main函数里面使用 */
/************************************************
* 函数名:FIFO_GPIO_Config
* 描述 :FIFO GPIO配置
* 输入 :无
* 输出 :无
* 注意 :无
************************************************/
static void FIFO_GPIO_Config(void)
{
//八位数据口
gpio_init(DATA_0,gpio_mode_input);
gpio_init(DATA_1,gpio_mode_input);
gpio_init(DATA_2,gpio_mode_input);
gpio_init(DATA_3,gpio_mode_input);
gpio_init(DATA_4,gpio_mode_input);
gpio_init(DATA_5,gpio_mode_input);
gpio_init(DATA_6,gpio_mode_input);
gpio_init(DATA_7,gpio_mode_input);
gpio_init(OE,gpio_mode_output);
gpio_init(WRST,gpio_mode_output);
gpio_init(RCLK,gpio_mode_output);
gpio_init(WE,gpio_mode_output);
FIFO_OE_L(); /*拉低使FIFO输出使能*/
FIFO_WE_H(); /*拉高使FIFO写允许*/
}
void VSYNC_handle(int irq, void *param) ////vsync中断处理函数
{
// if ( EXTI_GetITStatus(OV7725_VSYNC_EXTI_LINE) != RESET ) //检查EXTI_Line0线路上的中断请求是否发送到了NVIC
// {
//rt_kprintf("vsync中断处理函数\n");
if( Ov7725_vsync == 0 )
{
FIFO_WRST_L(); //拉低使FIFO写(数据from摄像头)指针复位
FIFO_WE_H(); //拉高使FIFO写允许
Ov7725_vsync = 1;
FIFO_WE_H(); //使FIFO写允许
FIFO_WRST_H(); //允许使FIFO写(数据from摄像头)指针运动
}
else if( Ov7725_vsync == 1 )
{
FIFO_WE_L(); //拉低使FIFO写暂停
Ov7725_vsync = 2;
}
// EXTI_ClearITPendingBit(OV7725_VSYNC_EXTI_LINE); //清除EXTI_Line0线路挂起标志位
// }
}
/************************************************
* 函数名:VSYNC_GPIO_Config
* 描述 :OV7725 VSYNC中断相关配置
* 输入 :无
* 输出 :无
* 注意 :无
************************************************/
static void VSYNC_GPIO_Config(void)
{
//初始化vsync中断
int VSYNC_irq = LS1C_GPIO_TO_IRQ(VSYNC);
gpio_set_irq_type(VSYNC, IRQ_TYPE_EDGE_FALLING);
rt_hw_interrupt_install(VSYNC_irq, VSYNC_handle, RT_NULL, "VSYNC");
rt_hw_interrupt_umask(VSYNC_irq);
gpio_init(VSYNC, gpio_mode_input);
//rt_kprintf("VSYNC interupt init succ \r\n", VSYNC_irq);
}
/************************************************
* 函数名:OV7725_GPIO_Config
* 描述 :初始化控制摄像头相接的IO
* 输入 :无
* 输出 :无
* 注意 :无
************************************************/
void OV7725_GPIO_Config(void)
{
i2c_Config();
FIFO_GPIO_Config();
VSYNC_GPIO_Config();
}
/**
* @brief ÉèÖùâÕÕ¶È
* @param bri:¹âÕնȣ¬²ÎÊý·¶Î§[-4~+4]
* @retval ÎÞ
*/
void OV7725_Brightness(rt_int8_t bri)
{
rt_uint8_t BRIGHT_Value,SIGN_Value;
switch(bri)
{
case 4:
BRIGHT_Value = 0x48;
SIGN_Value = 0x06;
break;
case 3:
BRIGHT_Value = 0x38;
SIGN_Value = 0x06;
break;
case 2:
BRIGHT_Value = 0x28;
SIGN_Value = 0x06;
break;
case 1:
BRIGHT_Value = 0x18;
SIGN_Value = 0x06;
break;
case 0:
BRIGHT_Value = 0x08;
SIGN_Value = 0x06;
break;
case -1:
BRIGHT_Value = 0x08;
SIGN_Value = 0x0e;
break;
case -2:
BRIGHT_Value = 0x18;
SIGN_Value = 0x0e;
break;
case -3:
BRIGHT_Value = 0x28;
SIGN_Value = 0x0e;
break;
case -4:
BRIGHT_Value = 0x38;
SIGN_Value = 0x0e;
break;
default:
OV7725_DEBUG("Brightness parameter error!");
break;
}
i2c_WriteByte(REG_BRIGHT, BRIGHT_Value); //AWB on
i2c_WriteByte(REG_SIGN, SIGN_Value);
}
/************************************************
* 函数名:Sensor_Init
* 描述 :Sensor初始化
* 输入 :无
* 输出 :返回1成功,返回0失败
* 注意 :无
************************************************/
int OV7725_Init(void)
{
rt_uint16_t i = 0;
rt_uint8_t Sensor_IDCode = 0;
// if( 0 == i2c_ReadByte( &Sensor_IDCode, 1, 0x0b ) ) /* 读取sensor ID号*/
// {
// rt_kprintf("read id faild\n");
// //return ERROR;
// }
// rt_kprintf("Sensor ID is 0x%x\n", Sensor_IDCode);
rt_kprintf("ov7725 Register Config Start......\n");
if( 0 == i2c_WriteByte ( 0x12, 0x80 ) ) /*复位sensor */
{
rt_kprintf("sccb write data error\n");
return ERROR ;
}
rt_thread_delay(20);
if( 0 == i2c_ReadByte( &Sensor_IDCode, 1, 0x0b ) ) /* 读取sensor ID号*/
{
rt_kprintf("read id faild\n");
return ERROR;
}
rt_kprintf("Sensor ID is 0x%x\n", Sensor_IDCode);
if(Sensor_IDCode == OV7725_ID)
{
//rt_kprintf("Sensor_IDCode == OV7725_ID\n");
for( i = 0 ; i < OV7725_REG_NUM ; i++ )
{
if( 0 == i2c_WriteByte(Sensor_Config.Address, Sensor_Config.Value) )
{
rt_kprintf("write reg faild", Sensor_Config.Address);
return ERROR;
}
rt_thread_delay(6);
// i2c_ReadByte( &Sensor_IDCode, 1, Sensor_Config.Address );
// rt_kprintf("Sensor ID is 0x%x\n", Sensor_IDCode);
// if(Sensor_Config.Value!=Sensor_IDCode)
// {
// rt_kprintf("write reg faild\n", Sensor_Config.Address);
// }
}
for( i = 0 ; i < OV7725_REG_NUM ; i++ )
{
i2c_ReadByte( &Sensor_IDCode, 1, Sensor_Config.Address );
rt_kprintf("reg is 0x%x\n", Sensor_IDCode);
int cc=0;
// while(Sensor_Config.Value!=Sensor_IDCode)
// {
// cc++;
// if(cc==30)
// {
// return;
// }
// //rt_kprintf(" write reg faild reg=%x\n", Sensor_IDCode);
// i2c_WriteByte(Sensor_Config.Address, Sensor_Config.Value);
// i2c_ReadByte( &Sensor_IDCode, 1, Sensor_Config.Address );
// if(Sensor_Config.Value!=Sensor_IDCode)
// {
// rt_kprintf(" cc=%d write reg faild reg=%x\n",cc, Sensor_IDCode);
// }
// else
// {
// rt_kprintf(" cc=%d write reg succ reg=%x\n",cc, Sensor_IDCode);
// }
// }
}
for( i = 0 ; i < OV7725_REG_NUM ; i++ )
{
i2c_ReadByte( &Sensor_IDCode, 1, Sensor_Config.Address );
if(Sensor_Config.Value!=Sensor_IDCode)
{
rt_kprintf("******* write reg faild reg=%x\n", Sensor_IDCode);
}
}
rt_kprintf("*******************************************************\n");
for( i = 0 ; i < OV7725_REG_NUM ; i++ )
{
i2c_ReadByte( &Sensor_IDCode, 1, Sensor_Config.Address );
if(Sensor_Config.Value!=Sensor_IDCode)
{
rt_kprintf("******* write reg faild reg=%x\n", Sensor_IDCode);
}
}
}
else
{
return ERROR;
}
//rt_kprintf("ov7725 Register Config Success");
return SUCCESS;
}
/**
* @brief 设置光照模式
* @param mode :光照模式,参数范围[0~5]
@arg 0:自动
@arg 1:晴天
@arg 2:多云
@arg 3:办公室
@arg 4:家里
@arg 5:夜晚
* @retval 无
*/
void OV7725_Light_Mode(rt_uint8_t mode)
{
switch(mode)
{
case 0: //Auto,自动模式
i2c_WriteByte(0x13, 0xff); //AWB on
i2c_WriteByte(0x0e, 0x65);
i2c_WriteByte(0x2d, 0x00);
i2c_WriteByte(0x2e, 0x00);
break;
case 1://sunny,晴天
i2c_WriteByte(0x13, 0xfd); //AWB off
i2c_WriteByte(0x01, 0x5a);
i2c_WriteByte(0x02, 0x5c);
i2c_WriteByte(0x0e, 0x65);
i2c_WriteByte(0x2d, 0x00);
i2c_WriteByte(0x2e, 0x00);
break;
case 2://cloudy,多云
i2c_WriteByte(0x13, 0xfd); //AWB off
i2c_WriteByte(0x01, 0x58);
i2c_WriteByte(0x02, 0x60);
i2c_WriteByte(0x0e, 0x65);
i2c_WriteByte(0x2d, 0x00);
i2c_WriteByte(0x2e, 0x00);
break;
case 3://office,办公室
i2c_WriteByte(0x13, 0xfd); //AWB off
i2c_WriteByte(0x01, 0x84);
i2c_WriteByte(0x02, 0x4c);
i2c_WriteByte(0x0e, 0x65);
i2c_WriteByte(0x2d, 0x00);
i2c_WriteByte(0x2e, 0x00);
break;
case 4://home,家里
i2c_WriteByte(0x13, 0xfd); //AWB off
i2c_WriteByte(0x01, 0x96);
i2c_WriteByte(0x02, 0x40);
i2c_WriteByte(0x0e, 0x65);
i2c_WriteByte(0x2d, 0x00);
i2c_WriteByte(0x2e, 0x00);
break;
case 5://night,夜晚
i2c_WriteByte(0x13, 0xff); //AWB on
i2c_WriteByte(0x0e, 0xe5);
break;
default:
OV7725_DEBUG("Light Mode parameter error!");
break;
}
}
/**
* @brief ÉèÖñ¥ºÍ¶È
* @param sat:±¥ºÍ¶È,²ÎÊý·¶Î§[-4 ~ +4]
* @retval ÎÞ
*/
void OV7725_Color_Saturation(rt_int8_t sat)
{
if(sat >=-4 && sat<=4)
{
i2c_WriteByte(REG_USAT, (sat+4)<<4);
i2c_WriteByte(REG_VSAT, (sat+4)<<4);
}
else
{
OV7725_DEBUG("Color Saturation parameter error!");
}
}
/**
* @brief 设置对比度
* @param cnst:对比度,参数范围[-4~+4]
* @retval 无
*/
void OV7725_Contrast(rt_int8_t cnst)
{
if(cnst >= -4 && cnst <=4)
{
i2c_WriteByte(REG_CNST, (0x30-(4-cnst)*4));
}
else
{
OV7725_DEBUG("Contrast parameter error!");
}
}
/**
* @brief 设置特殊效果
* @param eff:特殊效果,参数范围[0~6]:
@arg 0:正常
@arg 1:黑白
@arg 2:偏蓝
@arg 3:复古
@arg 4:偏红
@arg 5:偏绿
@arg 6:反相
* @retval 无
*/
void OV7725_Special_Effect(rt_uint8_t eff)
{
switch(eff)
{
case 0://正常
i2c_WriteByte(0xa6, 0x06);
i2c_WriteByte(0x60, 0x80);
i2c_WriteByte(0x61, 0x80);
break;
case 1://黑白
i2c_WriteByte(0xa6, 0x26);
i2c_WriteByte(0x60, 0x80);
i2c_WriteByte(0x61, 0x80);
break;
case 2://偏蓝
i2c_WriteByte(0xa6, 0x1e);
i2c_WriteByte(0x60, 0xa0);
i2c_WriteByte(0x61, 0x40);
break;
case 3://复古
i2c_WriteByte(0xa6, 0x1e);
i2c_WriteByte(0x60, 0x40);
i2c_WriteByte(0x61, 0xa0);
break;
case 4://偏红
i2c_WriteByte(0xa6, 0x1e);
i2c_WriteByte(0x60, 0x80);
i2c_WriteByte(0x61, 0xc0);
break;
case 5://偏绿
i2c_WriteByte(0xa6, 0x1e);
i2c_WriteByte(0x60, 0x60);
i2c_WriteByte(0x61, 0x60);
break;
case 6://反相
i2c_WriteByte(0xa6, 0x46);
break;
default:
OV7725_DEBUG("Special Effect error!");
break;
}
}
/**
* @brief 设置图像输出窗口(分辨率)QVGA
* @param sx:窗口x起始位置
* @param sy:窗口y起始位置
* @param width:窗口宽度
* @param height:窗口高度
* @param QVGA_VGA:0,QVGA模式,1,VGA模式
*
* @note QVGA模式 参数要求,sx + width <= 320 ,sy+height <= 240
* VGA模式参数要求,sx + width <= 640 ,sy+height <= 480
* 但由于 液晶屏分辨率 和 FIFO空间 的限制,本工程不适用于超过320*240的配置
* 使用VGA模式主要是因为OV7725无法直接交换XY方向,QVGA不方便使用竖平显示,
* 设置成VGA模式,可以使用竖屏显示,
* 相对QVGA模式,同样分辨率下 VGA模式 图像采样帧率稍慢
* @retval 无
*/
void OV7725_Window_Set(rt_uint16_t sx,rt_uint16_t sy,rt_uint16_t width,rt_uint16_t height,rt_uint8_t QVGA_VGA)
{
rt_uint8_t reg_raw,cal_temp;
/***********QVGA or VGA *************/
if(QVGA_VGA == 0)
{
/*QVGA RGB565 */
i2c_WriteByte(REG_COM7,0x46);
}
else
{
/*VGA RGB565 */
i2c_WriteByte(REG_COM7,0x06);
}
/***************HSTART*********************/
//读取寄存器的原内容,HStart包含偏移值,在原始偏移植的基础上加上窗口偏移
i2c_ReadByte(®_raw,1,REG_HSTART);
//sx为窗口偏移,高8位存储在HSTART,低2位在HREF
cal_temp = (reg_raw + (sx>>2));
i2c_WriteByte(REG_HSTART,cal_temp );
/***************HSIZE*********************/
//水平宽度,高8位存储在HSIZE,低2位存储在HREF
i2c_WriteByte(REG_HSIZE,width>>2);//HSIZE左移两位
/***************VSTART*********************/
//读取寄存器的原内容,VStart包含偏移值,在原始偏移植的基础上加上窗口偏移
i2c_ReadByte(®_raw,1,REG_VSTRT);
//sy为窗口偏移,高8位存储在HSTART,低1位在HREF
cal_temp = (reg_raw + (sy>>1));
i2c_WriteByte(REG_VSTRT,cal_temp);
/***************VSIZE*********************/
//垂直高度,高8位存储在VSIZE,低1位存储在HREF
i2c_WriteByte(REG_VSIZE,height>>1);//VSIZE左移一位
/***************VSTART*********************/
//读取寄存器的原内容
i2c_ReadByte(®_raw,1,REG_HREF);
//把水平宽度的低2位、垂直高度的低1位,水平偏移的低2位,垂直偏移的低1位的配置添加到HREF
cal_temp = (reg_raw |(width&0x03)|((height&0x01)<<2)|((sx&0x03)<<4)|((sy&0x01)<<6));
i2c_WriteByte(REG_HREF,cal_temp);
/***************HOUTSIZIE /VOUTSIZE*********************/
i2c_WriteByte(REG_HOutSize,width>>2);
i2c_WriteByte(REG_VOutSize,height>>1);
//读取寄存器的原内容
i2c_ReadByte(®_raw,1,REG_EXHCH);
cal_temp = (reg_raw |(width&0x03)|((height&0x01)<<2));
i2c_WriteByte(REG_EXHCH,cal_temp);
}
/**
* @brief 设置图像输出窗口(分辨率)VGA
* @param sx:窗口x起始位置
* @param sy:窗口y起始位置
* @param width:窗口宽度
* @param height:窗口高度
* @note 本函数参数要求,sx + width <= 640 ,sy+height <= 480
* 但由于 液晶屏分辨率 和 FIFO空间 的限制,本工程不适用于超过320*240的配置
* 使用本函数主要是因为OV7725无法直接交换XY方向,QVGA不方便使用竖平显示,
* 使用本函数设置成VGA模式,可以使用竖屏显示,
* 相对QVGA模式,同样分辨率下 VGA模式 图像采样帧率稍慢
* @retval 无
*/
void OV7725_Window_VGA_Set(rt_uint16_t sx,rt_uint16_t sy,rt_uint16_t width,rt_uint16_t height)
{
rt_uint8_t reg_raw,cal_temp;
/***********QVGA or VGA *************/
/*VGA RGB565 */
i2c_WriteByte(REG_COM7,0x06);
/***************HSTART*********************/
//读取寄存器的原内容,HStart包含偏移值,在原始偏移植的基础上加上窗口偏移
i2c_ReadByte(®_raw,1,REG_HSTART);
//sx为窗口偏移,高8位存储在HSTART,低2位在HREF
cal_temp = (reg_raw + (sx>>2));
i2c_WriteByte(REG_HSTART,cal_temp );
/***************HSIZE*********************/
//水平宽度,高8位存储在HSIZE,低2位存储在HREF
i2c_WriteByte(REG_HSIZE,width>>2);//HSIZE左移两位 320
/***************VSTART*********************/
//读取寄存器的原内容,VStart包含偏移值,在原始偏移植的基础上加上窗口偏移
i2c_ReadByte(®_raw,1,REG_VSTRT);
//sy为窗口偏移,高8位存储在HSTART,低1位在HREF
cal_temp = (reg_raw + (sy>>1));
i2c_WriteByte(REG_VSTRT,cal_temp);
/***************VSIZE*********************/
//垂直高度,高8位存储在VSIZE,低1位存储在HREF
i2c_WriteByte(REG_VSIZE,height>>1);//VSIZE左移一位 240
/***************VSTART*********************/
//读取寄存器的原内容
i2c_ReadByte(®_raw,1,REG_HREF);
//把水平宽度的低2位、垂直高度的低1位,水平偏移的低2位,垂直偏移的低1位的配置添加到HREF
cal_temp = (reg_raw |(width&0x03)|((height&0x01)<<2)|((sx&0x03)<<4)|((sy&0x01)<<6));
i2c_WriteByte(REG_VSTRT,cal_temp);
/***************HOUTSIZIE /VOUTSIZE*********************/
i2c_WriteByte(REG_HOutSize,width>>2);
i2c_WriteByte(REG_VOutSize,height>>1);
//读取寄存器的原内容
i2c_ReadByte(®_raw,1,REG_EXHCH);
cal_temp = (reg_raw |(width&0x03)|((height&0x01)<<2));
i2c_WriteByte(REG_EXHCH,cal_temp);
}
/**
* @brief 设置显示位置
* @param sx:x起始显示位置
* @param sy:y起始显示位置
* @param width:显示窗口宽度,要求跟OV7725_Window_Set函数中的width一致
* @param height:显示窗口高度,要求跟OV7725_Window_Set函数中的height一致
* @retval 无
*/
rt_uint8_t pic_l;
rt_uint8_t pic_h;
void ImagDisp(void)
{
int i;
rt_uint16_t RGB565;
//LCD_Clear(WHITE);
//rt_thread_delay(1000);
//rt_kprintf("这里全屏变白\n");
Lcd_SetRegion(0,0,127,159);
for(i = 0; i < 160; i++)
{
for(int j=0;j<128;j++)
{
RGB565=0;
FIFO_RCLK_L();
pic_l=get_data();
RGB565 = (pic_l) & 0xff00;
FIFO_RCLK_H();
FIFO_RCLK_L();
pic_h=get_data();
RGB565 |= (pic_h) & 0x00ff;
//RGB565 = (pic_h <<8) | pic_l;
FIFO_RCLK_H();
//rt_kprintf("pic_l=%x ",pic_l);
//rt_kprintf("pic_h=%x ",pic_h);
//rt_kprintf("RGB565=0x%x \n",RGB565);
/* 从FIFO读出一个rgb565像素到Camera_Data变量 */
lcd_write_data_16(RGB565);//液晶屏使用的不一样,所以这里注释掉
//rt_thread_delay(500);
}
//rt_kprintf("\n");
}
//rt_thread_delay(3000);
}
//定义图像数组全局变量
rt_uint16_t pic[128][160]={0};
void get_pic(void)
{
int i,j;
rt_uint16_t Camera_Data;
for(i=0;i<128;i++)
for(j=0;j<160;j++)
{
READ_FIFO_PIXEL(Camera_Data);
pic[j]=Camera_Data;
}
}
void ov(void)
{
int frame_count=0;
tft_init();
showimage(gImage_suse);//开机动画
OV7725_GPIO_Config();
int retry=0;
while(OV7725_Init()!=SUCCESS)
{
retry++;
if(retry==5)
{
rt_kprintf("init ov7725 failed....\n");
return;
}
}
OV7725_Special_Effect(cam_mode.effect);
OV7725_Light_Mode(cam_mode.light_mode);
OV7725_Color_Saturation(cam_mode.saturation);
OV7725_Brightness(cam_mode.brightness);
OV7725_Contrast(cam_mode.contrast);
OV7725_Special_Effect(cam_mode.effect);
OV7725_Window_Set( cam_mode.cam_sx,
cam_mode.cam_sy,
cam_mode.cam_width,
cam_mode.cam_height,
cam_mode.QVGA_VGA);
//OV7725_Window_VGA_Set(0,0,127,159);
Ov7725_vsync = 0;
while(1)
{
if( Ov7725_vsync == 2 )
{
frame_count++;
rt_kprintf("frame_count=%d \n",frame_count);
if(frame_count==10)
{return;}
FIFO_PREPARE;
ImagDisp();
//rt_thread_delay(3000);
rt_uint8_t Sensor_IDCode = 0;
for(int i = 0 ; i < OV7725_REG_NUM ; i++ )
{
i2c_ReadByte( &Sensor_IDCode, 1, Sensor_Config.Address );
if(Sensor_Config.Value!=Sensor_IDCode)
{
rt_kprintf("******* write reg faild reg=%x\n", Sensor_IDCode);
}
}
Ov7725_vsync = 0;
//LED1_TOGGLE;
}
}
}
MSH_CMD_EXPORT(ov, ov7725 test);
|