📄 saa7113h_api.c
字号:
/* created by antiscle <hzh12@tom.com> 2005/07/04*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <termios.h>#include <linux/fb.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <jpeglib.h>#define __user#include "videodev.h"#include "saa7113h_api.h"/****************************************************///#include "pxa_camera.h"#define WCAM_VIDIOCSCAMREG _IOW('v', 211, int)#define WCAM_VIDIOCGCAMREG _IOR('v', 212, int)#define WCAM_VIDIOCSCIREG _IOW('v', 213, int)#define WCAM_VIDIOCGCIREG _IOR('v', 214, int)#define WCAM_VIDIOCSINFOR _IOW('v', 215, int)#define WCAM_VIDIOCGINFOR _IOR('v', 216, int)#define CAMERA_IMAGE_FORMAT_YCBCR422_PACKED 15#define CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR 16#define STILL_IMAGE CAMERA_STILL//(1)#define VIDEO_START CAMERA_VIDEO//(0)#define VIDEO_STOP (-1)/****************************************************/#define MAIN_TEST#define USER_I2C_INIT //use i2c initialize#define FIXED_SOURCE_WIDTH 720#define FIXED_SOURCE_HEIGHT 625/****************************************************/struct reg_set_s { int val1; int val2;};#if defined(USER_I2C_INIT)#include <sys/time.h>static void delay_ms(long ms){/* struct timeval tvs, tve; struct timezone tzs, tze; if(!ms) return; gettimeofday(&tvs, &tzs); while(1) { long ds, dus; gettimeofday(&tve, &tze); dus = tve.tv_usec - tvs.tv_usec; if(dus<0) { dus += 1000000; tve.tv_sec--; } ds = tve.tv_sec - tvs.tv_sec; if((ds*1000000+dus)/1000>=ms) break; }*/ fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(0, &rfds); tv.tv_sec = 0; tv.tv_usec = ms*1000; select(1, &rfds, NULL, NULL, &tv);}#define CAMERA_I2C_ADDR 0x24#define CHIP_DELAY 0xFFstruct i2c_reg_t { int subaddr; int value;};static struct i2c_reg_t camera_regs[] = {{0x00, 0x00}, //ADR 0x00h PH7113_CHIP_VERSION 00 - ID byte{0x01, 0x08}, //ADR 0x01h PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0{0x02, 0xc0}, //ADR 0x02h PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0{0x03, 0x23}, //ADR 0x03h PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18{0x04, 0x00}, //ADR 0x04h PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10{0x05, 0x00}, //ADR 0x05h PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20{0x06, 0xe9}, //ADR 0x06h PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0{0x07, 0x0d}, //ADR 0x07h PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0{0x08, 0x98}, //ADR 0x08h PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0{0x09, 0x01}, //ADR 0x09h PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0{0x0a, 0x80}, //ADR 0x0ah PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0{0x0b, 0x47}, //ADR 0x0bh PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0{0x0c, 0x40}, //ADR 0x0ch PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0{0x0d, 0x00}, //ADR 0x0dh PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0{0x0e, 0x05}, //ADR 0x0eh PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0{0x0f, 0x24}, //ADR 0x0fh PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0{0x10, 0x00}, //ADR 0x10h PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0{0x11, 0x1d},//0x1c//ADR 0x11h PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO{0x12, 0xa7},//0xc7 , //ADR 0x12h PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 //RTS0 is VLINE,RTS1 is VFRAME{0x13, 0x81},//0x01//ADR 0x13h PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0{0x14, 0x00}, //ADR 0x14h RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1){0x15, 0x38}, //ADR 0x15h PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0{0x16, 0x00}, //ADR 0x16h PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0{0x17, 0x01}, //ADR 0x17h PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8{0x18, 0x00}, //ADR 0x18h{0x19, 0x00}, //ADR 0x19h{0x1a, 0x00}, //ADR 0x1ah{0x1b, 0x00}, //ADR 0x1bh{0x1c, 0x00}, //ADR 0x1ch{0x1d, 0x00}, //ADR 0x1dh{0x1e, 0x00}, //ADR 0x1eh{0x1f, 0x00}, //ADR 0x1fh{0x20, 0x00}, //ADR 0x20h{0x21, 0x00}, //ADR 0x21h{0x22, 0x00}, //ADR 0x22h{0x23, 0x00}, //ADR 0x23h{0x24, 0x00}, //ADR 0x24h{0x25, 0x00}, //ADR 0x25h{0x26, 0x00}, //ADR 0x26h{0x27, 0x00}, //ADR 0x27h{0x28, 0x00}, //ADR 0x28h{0x29, 0x00}, //ADR 0x29h{0x2a, 0x00}, //ADR 0x2ah{0x2b, 0x00}, //ADR 0x2bh{0x2c, 0x00}, //ADR 0x2ch{0x2d, 0x00}, //ADR 0x2dh{0x2e, 0x00}, //ADR 0x2eh{0x2f, 0x00}, //ADR 0x2fh{0x30, 0x00}, //ADR 0x30h{0x31, 0x00}, //ADR 0x31h{0x32, 0x00}, //ADR 0x32h{0x33, 0x00}, //ADR 0x33h{0x34, 0x00}, //ADR 0x34h{0x35, 0x00}, //ADR 0x35h{0x36, 0x00}, //ADR 0x36h{0x37, 0x00}, //ADR 0x37h{0x38, 0x00}, //ADR 0x38h{0x39, 0x00}, //ADR 0x39h{0x3a, 0x00}, //ADR 0x3ah{0x3b, 0x00}, //ADR 0x3bh{0x3c, 0x00}, //ADR 0x3ch{0x3d, 0x00}, //ADR 0x3dh{0x3e, 0x00}, //ADR 0x3eh{0x3f, 0x00}, //ADR 0x3fh{0x40, 0x02}, //ADR 0x40h{0x41, 0xff}, //ADR 0x41h{0x42, 0xff}, //ADR 0x42h{0x43, 0xff}, //ADR 0x43h{0x44, 0xff}, //ADR 0x44h{0x45, 0xff}, //ADR 0x45h{0x46, 0xff}, //ADR 0x46h{0x47, 0xff}, //ADR 0x47h{0x48, 0xff}, //ADR 0x48h{0x49, 0xff}, //ADR 0x49h{0x4a, 0xff}, //ADR 0x4ah{0x4b, 0xff}, //ADR 0x4bh{0x4c, 0xff}, //ADR 0x4ch{0x4d, 0xff}, //ADR 0x4dh{0x4e, 0xff}, //ADR 0x4eh{0x4f, 0xff}, //ADR 0x4fh{0x50, 0xff}, //ADR 0x50h{0x51, 0xff}, //ADR 0x51h{0x52, 0xff}, //ADR 0x52h{0x53, 0xff}, //ADR 0x53h{0x54, 0xff}, //ADR 0x54h{0x55, 0xff}, //ADR 0x55h{0x56, 0xff}, //ADR 0x56h{0x57, 0xff}, //ADR 0x57h{0x58, 0x00}, //ADR 0x58h{0x59, 0x54}, //ADR 0x59h{0x5a, 0x07}, //ADR 0x5ah{0x5b, 0x83}, //ADR 0x5bh{0x5c, 0x00}, //ADR 0x5ch{0x5d, 0x00}, //ADR 0x5dh{0x5e, 0x00}, //ADR 0x5eh{0x5f, 0x00}, //ADR 0x5fh{0x60, 0x00}, //ADR 0x60h{0x61, 0x00}, //ADR 0x61h{0x62, 0x00} //ADR 0x62h};#define CAMERA_REGS (sizeof(camera_regs)/sizeof(camera_regs[0]))#endif#ifdef USER_I2C_INITstatic int i2c_write(int fd, __u8 reg, __u8 val){ int retries; __u8 data[2]; data[0] = reg; data[1] = val; for(retries=8; retries; retries--) { if(write(fd, data, 2)==2) return 0; delay_ms(2); } //printf("write fail %x %x\n", data[0], data[1]); return -1;}static int i2c_read(int fd, __u8 reg, __u8 *val){ int retries; for(retries=8; retries; retries--) { if(write(fd, ®, 1)==1) if(read(fd, val, 1)==1) return 0; delay_ms(2); } //printf("read fail\n"); return -1;}#define I2C_SLAVE 0x0703 /* Change slave address */static int camera_i2c_init(void){ int i, fd; __u8 id[4]; //delay_ms(100); printf("open i2c device...\n"); fd = open("/dev/i2c/0", O_RDWR); if(fd<0) { fd = open("/dev/misc/i2c", O_RDWR); if(fd<0) { printf("fail to open i2c adapter device!\n"); return -1; } } if(ioctl(fd, I2C_SLAVE, CAMERA_I2C_ADDR)<0) { printf("fail to set i2c device slave address!\n"); close(fd); return -1; } printf("set slave address to 0x%x success!\n", CAMERA_I2C_ADDR); if(i2c_read(fd, 0, id)) { printf("fail to get camera chip version!\n"); close(fd); return -1; } printf("chip version is 0x%02x\n", id[0]); i2c_read(fd, 0x1f, id+1); printf("decoder status is 0x%02x\n", id[1]); for(i=0; i<CAMERA_REGS; i++) { if(camera_regs[i].subaddr==CHIP_DELAY) delay_ms(camera_regs[i].value); else if(i2c_write(fd, camera_regs[i].subaddr, camera_regs[i].value)) printf("write subaddr 0x%x fail!\n", camera_regs[i].subaddr); //delay_ms(2); //printf("%d\n", i); }// if(cpu_type==1) { //s3c2440a// i2c_write(fd, 0x15, 0x00); //always has PCLK// i2c_write(fd, 0x3a, 0x01); //YCbYCr order// } close(fd); return 0;}#else#define camera_i2c_init() 0#endif/*************************************************************/#define CAMERA_DEVNAME "/dev/v4l/video0"static int cam_fd = -1;static char *cam_buf = NULL;static char *cam_y_buf;static char *cam_cb_buf;static char *cam_cr_buf;static int cam_buf_size;static __u16 line_idx[1024];static char *line_y[1024];static char *line_cb[1024];static char *line_cr[1024];static char *image_line[1024];static unsigned char *image_buffer = NULL;static unsigned short image_width;static unsigned short image_height;static unsigned short image_format;static unsigned short mmap_camera;static unsigned short capture_video;static unsigned short cpu_type;static cam_window_t *cam_win_p = NULL;static struct { int palette; char *name;} optional_image_format[] = { { VIDEO_PALETTE_YUV422P, "YCbCr422 planar", }, { VIDEO_PALETTE_RGB565, "RGB565", },/* { VIDEO_PALETTE_RGB24, "RGB24", },*/};#define MAX_IMAGE_FORMAT (sizeof(optional_image_format)/sizeof(optional_image_format[0]))static cam_window_t sub_win_pos[] = { {0, 0, 720, 624, 1, 1}, {0, 0, 720, 624, 2, 2}, {0, 0, 720, 624, 3, 3}, {0, 0, 720, 624, 4, 4}, {180, 156, 540, 468, 1, 1}, {0, 0, 360, 312, 1, 1}, {360, 0, 720, 312, 1, 1}, {0, 312, 360, 624, 1, 1}, {360, 312, 720, 624, 1, 1}, {0, 0, 240, 208, 1, 1}, {240, 0, 480, 208, 1, 1}, {480, 0, 720, 208, 1, 1}, {0, 208, 240, 416, 1, 1}, {240, 208, 480, 416, 1, 1}, {480, 208, 720, 416, 1, 1}, {0, 416, 240, 624, 1, 1}, {240, 416, 480, 624, 1, 1}, {480, 416, 720, 624, 1, 1}, {40, 72, 680, 552, 1, 1}, {40, 72, 680, 552, 2, 2}, {200, 192, 520, 432, 1, 1}, {168, 168, 552, 456, 1, 1}, {9, 24, 711, 600, 3, 3},};#define SUB_WIN_NUMBER (sizeof(sub_win_pos)/sizeof(cam_window_t))int camera_open(int cpu){ int i; struct video_capability vc; struct video_window vw; struct video_capture vcp; struct video_picture vp; struct video_mbuf vm; cam_fd = open(CAMERA_DEVNAME, O_RDONLY); //rd&wr if(cam_fd<0) { fprintf(stderr, "Open camera fail!\n"); return -ENODEV; } else fprintf(stdout, "Open camera success.\n"); image_width = FIXED_SOURCE_WIDTH; image_height = FIXED_SOURCE_HEIGHT; image_format = 0; //YCbCr4:2:2 cpu_type = cpu; mmap_camera = 1; if(camera_i2c_init()) { fprintf(stderr, "fail to initialize the I2C interface of camera!\n"); camera_close(); return -ENODEV; } if(ioctl(cam_fd, VIDIOCGCAP, &vc)<0) fprintf(stderr, "VIDIOCGCAP fail!\n"); else fprintf(stdout, "max width %d, height %d\nmin width %d, height %d\n", vc.maxwidth, vc.maxheight, vc.minwidth, vc.minheight); vw.width = FIXED_SOURCE_WIDTH; //fixed in this application vw.height = FIXED_SOURCE_HEIGHT; //fixed in this application if(ioctl(cam_fd, VIDIOCSWIN, &vw)<0) fprintf(stderr, "VIDIOCSWIN fail!\n"); if(ioctl(cam_fd, VIDIOCGWIN, &vw)<0) fprintf(stderr, "VIDIOCGWIN fail!\n"); else fprintf(stdout, "current width %d, height %d\n", vw.width, vw.height); if(!image_width||!image_height) { image_width = vw.width; image_height = vw.height; } //used in s3c2440a vcp.width = image_width; vcp.height = image_height; if(ioctl(cam_fd, VIDIOCSCAPTURE, &vcp)<0) fprintf(stderr, "VIDIOCSCAPTURE fail!\n"); else { if(ioctl(cam_fd, VIDIOCGCAPTURE, &vcp)<0) fprintf(stderr, "VIDIOCGCAPTURE fail!\n"); else fprintf(stdout, "capture width %d, height %d\n", vcp.width, vcp.height); } vp.palette = optional_image_format[image_format].palette; if(ioctl(cam_fd, VIDIOCSPICT, &vp)<0) fprintf(stderr, "VIDIOCSPICT fail!\n"); if(ioctl(cam_fd, VIDIOCGPICT, &vp)<0) fprintf(stderr, "VIDIOCGPICT fail!\n"); else fprintf(stdout, "current palette %d\n", vp.palette); if(cpu_type==1) { if(ioctl(cam_fd, VIDIOCSYCbCr, 2)<0) { fprintf(stderr, "fail to set YCbCr order!\n"); } } if(cpu_type==PXA27X) { struct reg_set_s reg; //extend ioctl, just in pxa270 reg.val1 = CAMERA_IMAGE_FORMAT_YCBCR422_PACKED; //input format for pxa270 reg.val2 = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR; //output format for pxa270 if(ioctl(cam_fd, WCAM_VIDIOCSINFOR, ®)<0) fprintf(stderr, "WCAM_VIDIOCSINFOR fail!\n"); if(ioctl(cam_fd, WCAM_VIDIOCGINFOR, ®)<0) fprintf(stderr, "WCAM_VIDIOCGINFOR fail!\n"); else fprintf(stdout, "current input format %d, output format %d\n", reg.val1, reg.val2); } if(mmap_camera) { if(ioctl(cam_fd, VIDIOCGMBUF, &vm)<0) { fprintf(stderr, "VIDIOCGMBUF fail!\n"); mmap_camera = 0; } else { fprintf(stdout, "current camera buffer size %d, total frames %d.\n", vm.size, vm.frames); cam_buf = (__u8 *)mmap(0, vm.size, PROT_READ, MAP_SHARED, cam_fd, 0); if((int)cam_buf==-1) { fprintf(stderr, "mmap camera fail!\n"); cam_buf = NULL; mmap_camera = 0; } else { cam_buf_size = vm.size; fprintf(stdout, "mmap camera ok.\n"); } } } if(!mmap_camera) { fprintf(stdout, "allocate memory for camera buffer.\n"); cam_buf_size = image_width*image_height*2; cam_buf = malloc(cam_buf_size); if(cam_buf==NULL) { fprintf(stderr, "fail to allocate memory for camera!\n"); camera_close(); return -ENOMEM; } }// fprintf(stdout, "buffer at 0x%08x\n", (int)cam_buf); cam_y_buf = cam_buf; cam_cb_buf = cam_y_buf + image_height*image_width; cam_cr_buf = cam_cb_buf + image_height*image_width/2; for(i=0; i<625; i+=2) { line_idx[i] = i/2; line_idx[i+1] = i/2 + 313; } for(i=0; i<625; i++) { line_y[i] = cam_y_buf + line_idx[i]*image_width; line_cb[i] = cam_cb_buf + line_idx[i]*image_width/2; line_cr[i] = cam_cr_buf + line_idx[i]*image_width/2; } image_buffer = malloc(image_height*image_width*3); //RGB24 if(image_buffer==NULL) { fprintf(stderr, "allocate memory fail in saving picture!\n"); camera_close(); return -ENOMEM; } for(i=0; i<SUB_WIN_NUMBER; i++) { sub_win_pos[i].width = (sub_win_pos[i].x1 - sub_win_pos[i].x0) / sub_win_pos[i].x_ratio; sub_win_pos[i].height = (sub_win_pos[i].y1 - sub_win_pos[i].y0) / sub_win_pos[i].y_ratio; } return cam_fd;}int camera_close(void){ if(cam_fd>=0) { if(image_buffer!=NULL) { free(image_buffer); image_buffer = NULL; } if(cam_buf!=NULL) { if(mmap_camera) munmap(cam_buf, cam_buf_size); else free(cam_buf); cam_buf = NULL; } close(cam_fd); cam_fd = -1; } return 0;}int camera_start(int mode){ capture_video = (mode==CAMERA_VIDEO) ? 1 : 0; if(capture_video) { if(ioctl(cam_fd, VIDIOCCAPTURE, VIDEO_START)<0) { fprintf(stderr, "VIDIOCCAPTURE fail!\n"); return -ENOSYS; } } else if(cpu_type==PXA27X) { if(ioctl(cam_fd, VIDIOCCAPTURE, STILL_IMAGE)<0) { fprintf(stderr, "VIDIOCCAPTURE fail!\n"); return -ENOSYS; } } return 0;}int camera_stop(void){ if(capture_video) {// if(ioctl(cam_fd, VIDIOCCAPTURE, VIDEO_STOP)<0) {// fprintf(stderr, "VIDIOCCAPTURE fail!\n");// return -ENOSYS;// } } return 0;}int camera_capture(void){ //in pxa270, if capture still image, can do it just one time if(!capture_video&&cpu_type!=PXA27X) if(ioctl(cam_fd, VIDIOCCAPTURE, STILL_IMAGE)<0) { fprintf(stderr, "VIDIOCCAPTURE fail!\n"); return -EIO; } return 0;}int camera_get_window(unsigned int idx, cam_window_t *win){ if(idx>=SUB_WIN_NUMBER) return -EINVAL; *win = sub_win_pos[idx]; return 0;}int camera_set_window(cam_window_t *win){ int w, h; w = win->x1 - win->x0; h = win->y1 - win->y0; if(win->x0>=win->x1 || win->y0>=win->y1) return -EINVAL; if(win->x1>720 || win->y1>624) return -EINVAL; if(!win->x_ratio || !win->y_ratio) return -EINVAL; if(w&1) return -EINVAL; if((w%win->x_ratio) && (h%win->y_ratio)) return -EINVAL; win->width = w / win->x_ratio; win->height = h / win->y_ratio; sub_win_pos[SUBWIN_USER] = *win; return 0;}static __inline void convert_rgb16_image(void *buf, int format, cam_window_t *win);static __inline void convert_rgb24_image(void *buf, int format, cam_window_t *win);int camera_output_lines(void *buf, int format, cam_window_t *win){ int ret, rgb24; if(mmap_camera) {#if 1 //just for performance test in video capturing, int(rdy)->show->int->show //use read to clear ready flag in driver ret = read(cam_fd, cam_buf, 0); //mmap camera for read, so read 0 byte to buf if(ret<0) { fprintf(stderr, "read camera fail!%d\n", ret);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -