📄 camera.c
字号:
return value;
}
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
void __inline ov9650_config(void)
{
int i;
for (i = 0; i < OV9650_REGS; i++)
{
if (ov9650_reg[i].subaddr == CHIP_DELAY)
Delay(ov9650_reg[i].value);
else
ov9650_sccb_sendbyte(ov9650_reg[i].subaddr & 0xff, ov9650_reg[i].value & 0xff);
}
}
/********** start of S/W YUV2RGB ************/
#define XLATTABSIZE 256
#define MulDiv(x, y, z) ((long)((int) x * (int) y) / (int) z)
//#define CLIP(x) min_t(int, 255, max_t(int, 0, (x)))
#define CLIP(x) {if(x<0) x=0;if(x>255) x=255;}
#define RED_REGION 0xf800
#define GREEN_REGION 0x07e0
#define BLUE_REGION 0x001f
int XlatY[XLATTABSIZE] = { 0 };
int XlatV_B[XLATTABSIZE] = { 0 };
int XlatV_G[XLATTABSIZE] = { 0 };
int XlatU_G[XLATTABSIZE] = { 0 };
int XlatU_R[XLATTABSIZE] = { 0 };
#define ORIG_XLAT 1
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
void init_yuvtable (void)
{
int i, j;
for (i = 0; i < XLATTABSIZE; i++) {
#if ORIG_XLAT
j = min(253, max(16, i));
#else
j = (255 * i + 110) / 220; // scale up
j = min(255, max(j, 16));
#endif
// orig: XlatY[i] = (int ) j;
XlatY[i] = j-16;
}
for (i = 0; i < XLATTABSIZE; i++) {
#if ORIG_XLAT
j = min(240, max(16, i));
j -= 128;
#else
j = i - 128; // make signed
if (j < 0)
j++; // noise reduction
j = (127 * j + 56) / 112; // scale up
j = min(127, max(-128, j));
#endif
XlatV_B[i] = MulDiv (j, 1000, 564); /* j*219/126 */
XlatV_G[i] = MulDiv (j, 1100, 3328);
XlatU_G[i] = MulDiv (j, 3100, 4207);
XlatU_R[i] = MulDiv (j, 1000, 713);
}
}
#define MORE_QUALITY 1
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
void __inline yuv_convert_rgb16(unsigned char *rawY, unsigned char *rawU,
unsigned char *rawV, unsigned short *rgb, int size)
{
unsigned short buf1, buf3;
int red;
int blue;
int green;
unsigned long cnt;
int Y, U, V;
unsigned short data;
unsigned short data2;
for ( cnt = 0 ; cnt < size; cnt +=2)
{
buf1 = rawY[cnt] & 0xff; // Y data
buf3 = rawY[cnt+1] & 0xff; // Y data
U = rawV[cnt/2] & 0xff;
V = rawU[cnt/2] & 0xff;
#if MORE_QUALITY
Y = buf1;
#else
Y = ((buf1+buf3)/2);
#endif
red = XlatY[Y] + XlatU_R[U];
CLIP(red);
green = XlatY[Y] - XlatV_G[V] - XlatU_G[U];
CLIP(green);
blue = XlatY[Y] + XlatV_B[V];
CLIP(blue);
data = ((red << 8) & RED_REGION)
| ((green << 3) & GREEN_REGION)
| (blue >> 3);
#if MORE_QUALITY
Y = buf3;
red = XlatY[Y] + XlatU_R[U];
CLIP(red);
green = XlatY[Y] - XlatV_G[V] - XlatU_G[U];
CLIP(green);
blue = XlatY[Y] + XlatV_B[V];
CLIP(blue);
data2 = ((red << 8) & RED_REGION)
| ((green << 3) & GREEN_REGION)
| (blue >> 3);
#else
data2 = data;
#endif
rgb[2 * cnt] = data;
rgb[2 * (cnt + 1)]= data2;
}
}
/********** end of S/W YUV2RGB ******************/
/*********************************************************************************************************
** 函数名称:
** 功能描述: 使用PWM4输出占空比可调的PWM波形。
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
void SetCAMClockDivider(void)
{
PINSEL0 = (PINSEL0&0xFFFCFFFF)|0x00020000; // 设置PWM4连接到P0.8管脚
PWMPR = 0x00; // 不分频,计数频率为Fpclk
PWMMCR = 0x02; // 设置PWMMR0匹配时复位PWMTC
PWMMR0 = CYCLE_DATA; // 设置PWM周期
PWMMR4 = DUTY_CYCLE_DATA; // 设置PWM占空比
PWMLER = 0x11; // PWMMR0、PWMMR4锁存
PWMPCR = 0x1000; // 允许PWM4输出,单边PWM
PWMTCR = 0x09; // 启动定时器,PWM使能
}
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
int __inline check_ov9650(void)
{
int ret = 0;
int ov9650_mid = 0;
int try_count =0; //2 times
try_again:
ov9650_mid = (ov9650_sccb_receivebyte(0x1c) << 8);
ov9650_mid |= ov9650_sccb_receivebyte(0x1d);
if (ov9650_mid != OV9650_PRODUCT_ID)
{
if (!try_count++) goto try_again;
ret = -2;
} else {
}
//--- hzh, for ov9650
ov9650_mid = (ov9650_sccb_receivebyte(0x0a) << 8);
ov9650_mid |= ov9650_sccb_receivebyte(0x0b);
return ret;
}
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
int Test_OV9650(void)
{
int ret;
init_yuvtable();
CamPortSet();
ov9650_Init();
ret = check_ov9650() ;
if (ret) {
return ret; //错误指示
}
ov9650_config();
return 0;
}
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
int Test_CamPreview(void)
{
unsigned int i, j;
TCOLOR bakc;
yuv_convert_rgb16(Cam_outY, Cam_outU,Cam_outV, RGBBuffer, Preview_size);
for(i=0;i<SCR_YSIZE_TFT_240320;i++)
{
for(j=0;j<SCR_XSIZE_TFT_240320;j++)
{
bakc=(RGBBuffer[(2*j)]<<8) | (RGBBuffer[(2*j)+1]) ;//将RGB数据转化为16位索引值
GUI_Point(j, i, bakc);
}
}
return(1);
}
/*********************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入:
**
** 输 出:
** 全局变量:
** 调用模块:
********************************************************************************************************/
void Camera_Task(void *pdata)
{
int i;
uint8 err;
void *flag;
pdata = pdata;
OSTaskSuspend(3);
OSTaskSuspend(4);
OSTaskSuspend(5);
CamMbox = OSMboxCreate(NULL); // 建立一个邮箱,用于传递摄像头消息
#if (USED_CAM_TYPE==CAM_OV9650) //hzh
SetCAMClockDivider();
i = Test_OV9650();
if( i )
{
IO2CLR |= LED1;//Led_on1();//错误指示
OSTaskResume(3);
OSTaskResume(4);
OSTaskResume(5);
OSTaskDel(OS_PRIO_SELF);
return ;
}
#endif
Led_on2();//正确指示
VICIntEnable = (1<<15)|(1<<16)|(1<<17); // 使EINT0中断
while(1)
{
flag = OSMboxPend(CamMbox, 0, &err);
switch((int)flag)
{
case 00:
case 01:
break;
case CAM_FRAME_END:
VICIntEnClr=(1<<15)|(1<<16)|(1<<17); // 禁止EINT0中断
Test_CamPreview();
Frame_Flag=0;//一次显示完成
OSTimeDly(OS_TICKS_PER_SEC / 10);
VICIntEnable = (1<<15)|(1<<16)|(1<<17); // 使EINT0中断
break;
default:
break;
}
}
OSTaskResume(3);
OSTaskResume(4);
OSTaskResume(5);
OSTaskDel(OS_PRIO_SELF);
// stop camera //Init()Lcd_Tft
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -