可以帮忙调试,QQ:778292363
XS5013 芯片是一款应用于专业安防摄像机的图像信号处理芯片,主要应用在模拟摄像机产 品,高度集成外围器件,简化产品设计。内置高性能 ISP 处理器,最高支持 5M ,标清模拟输出 支持 960H ,高清模拟输出支持多标准协议,支持 720P/1080P/4M/5M ,其中 HDCVI 高清编码在 TX 模式下可支持到 720P/1080P/4M/5M/4K 。内嵌 CPU 处理器,可以实现灵活的软件应用。
XS5013 是面向中低端模拟摄像机产品的一款SOC 芯片。XS5013 既可以作为ISP+TX 单芯 片解决方案,也可以只当做TX 模块进行模拟视频编码。
此文章主要讲解TX 模块进行模拟视频编码,bt1120转ahd tvi cvi格式。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <ctype.h> #include <fcntl.h> #include <unistd.h> #include <termios.h> //set baud rate #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <errno.h> #include <sys/stat.h> /* cvi 720P60 pattern xs5013 "mem w 0x11003400 0x0" xs5013 "mem w 0x11000060 0x0011" xs5013 "mem w 0x11000060 0x1003" xs5013 "mem w 0x11001010 0x0" xs5013 "mem w 0x11001010 0xffffffff" xs5013 "mem w 0x11048080 0x03" xs5013 "mem w 0x11008188 0xff" xs5013 "mem w 0x11008188 0x0" xs5013 "mem w 0x1104805c 0x1" xs5013 "mem w 0x11003400 0x1" */ #define TTY_NAME "/dev/ttyS3" #define BAUDRATE B115200 #define XS_SUCCESS 0 #define XS_FAIL 1 // #define PKG_HEAD 0x02 #define PKG_TAIL 0x03 #define IMG_ADDRESS (0x00010000) #define XS_ADDRESS_LEN (4) #define XS_COUNT_LEN (4) #define XS_PERDATA_LEN (4) // command #define BM_CMD_NOTIFY 36 #define BM_CMD_DEBUG 20 #define BM_CMD_DLOAD 24 #define BM_CMD_WRITE 25 #define BM_CMD_READ 26 #define BM_CMD_RUN 27 #define BM_CMD_EXIT 101 #define BM_CMD_SHAKE 85 #define BM_CMD_ACK 170 #define BM_CMD_OK 5 #define BM_CMD_ERR 10 #define MB_CMD_MINIBOOT 117 #define MB_CMD_ERASE 69 enum { STX = 0, CMD, CHKSUM, ETX, HEADLEN, extDATA = HEADLEN }; typedef struct { char stx; char cmd; char chksum; char etx; }NoDataCmd; static NoDataCmd NoDataCmdPkg = { .stx = PKG_HEAD, .cmd = 0, .chksum = 0, .etx = PKG_TAIL }; // hexdump -v -e '4/1 "0x%02x, " "\n"' miniboot_reload_xs5013_ahd.img > ahdData static const char ahdData[] = { #include "ahdData" }; // hexdump -v -e '4/1 "0x%02x, " "\n"' miniboot_reload_xs5013_cvi.img > cviData static const char cviData[] = { #include "cviData" }; // hexdump -v -e '4/1 "0x%02x, " "\n"' miniboot_reload_xs5013_tvi.img > tviData static const char tviData[] = { #include "tviData" }; // hexdump -v -e '4/1 "0x%02x, " "\n"' pattern.img > patternData static const char patternData[] = { #include "patternData" }; static inline int bytes2int(char *buf) { return buf[3] |(buf[2]<<24) | (buf[1]<<16) | (buf[0]); } static inline void int2bytes(int i, char *buf) { buf[0] = (i>>24)&0xff; buf[1] = (i>>16)&0xff; buf[2] = (i>>8)&0xff; buf[3] = i&0xff; } int setOpt(int fd) { struct termios newtio, oldtio; if (tcgetattr(fd, &oldtio) != 0) { perror("SetupSerial"); return -1; } bzero(&newtio, sizeof(newtio)); newtio.c_lflag &= ~ECHO; cfsetispeed(&newtio, BAUDRATE); cfsetospeed(&newtio, BAUDRATE); #if 1 newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; newtio.c_cflag |= CS8; newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~CSTOPB; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; tcflush(fd, TCIFLUSH); #endif if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) { perror("com set error"); return -1; } return 0; } int readbytes(int fd, char *rcv_buf, int Len) { int ret=0, pos, time=0; fd_set rfds; struct timeval tv; pos = 0; while (pos < Len && time <3*Len) { FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = 0; //set the rcv wait time tv.tv_usec = 100*1000; //100000us = 0.1s ret = select(fd + 1, &rfds, NULL, NULL, &tv); time ++; if (ret == -1){ perror("select()"); continue; } else if (ret) { ret = read(fd, rcv_buf+pos, 1); //printf("[hardy] ret:%d 0x%02x\n", ret, *(rcv_buf + pos)); pos++; } else { //printf("[hardy]: timeout\n"); continue; } } return pos; } int readPckHead(int fd, char *rcv_buf) { int ret, trytimes=3; memset(rcv_buf, 0, HEADLEN); while (trytimes > 0) { trytimes--; if (PKG_HEAD != rcv_buf[STX]) { ret = readbytes(fd, rcv_buf, 1); if (ret < 0) continue; } if (PKG_HEAD == rcv_buf[STX]) { // read package head ret = readbytes(fd, &rcv_buf[CMD], HEADLEN-1); if (ret < 0) continue; if (PKG_TAIL == rcv_buf[ETX]) { break; } } } //printf("recv package head [0x%02x%02x%02x%02x]\n", rcv_buf[STX], rcv_buf[CMD], rcv_buf[CHKSUM], rcv_buf[ETX]); return (PKG_HEAD != rcv_buf[STX] || PKG_TAIL != rcv_buf[ETX]); } int sendDataTty(int fd, char *send_buf, int Len) { ssize_t ret; ret = write(fd, send_buf, Len); if (ret == -1) { printf("write device error\n"); return XS_FAIL; } return XS_SUCCESS; } static inline int sendNoDataCmd(int fd, char cmd) { NoDataCmdPkg.cmd = cmd; sendDataTty(fd, (char*)&NoDataCmdPkg, sizeof(NoDataCmdPkg)); printf("send [0x%02x%02x%02x%02x]\n", NoDataCmdPkg.stx, NoDataCmdPkg.cmd, NoDataCmdPkg.chksum, NoDataCmdPkg.etx); } int exeCmdDLoad(int fd, const char *mode) { #define DATA_NUM (0x200) char snd_buf[HEADLEN+XS_ADDRESS_LEN+XS_COUNT_LEN+DATA_NUM*XS_PERDATA_LEN] = {PKG_HEAD, BM_CMD_DLOAD, 0, PKG_TAIL}; int sentlen = 0; // int sendlen = 0; // data lenght will be sent const char* imgData = NULL; int datasize = 0;; int i, tryTimes, allDataLen; char rcv_buf[HEADLEN] = {0}; if (0 == strcmp(mode, "cvi")) { imgData = cviData; datasize = sizeof(cviData); } else if (0 == strcmp(mode, "tvi")) { imgData = tviData; datasize = sizeof(tviData); } else if (0 == strcmp(mode, "ahd")) { imgData = ahdData; datasize = sizeof(ahdData); } else { imgData = patternData; datasize = sizeof(patternData); } while (sentlen < datasize) { if (DATA_NUM*XS_PERDATA_LEN < (datasize-sentlen)) { sendlen = DATA_NUM*XS_PERDATA_LEN; } else { sendlen = datasize-sentlen; } //printf("will send len:0x%x\n", sendlen); // address int2bytes(IMG_ADDRESS+sentlen, snd_buf+HEADLEN); // count int2bytes(sendlen/XS_PERDATA_LEN, snd_buf+HEADLEN+XS_ADDRESS_LEN); // data memcpy(snd_buf+HEADLEN+XS_ADDRESS_LEN+XS_COUNT_LEN, imgData+sentlen, sendlen); // chksum allDataLen = HEADLEN+XS_ADDRESS_LEN+XS_COUNT_LEN+sendlen; snd_buf[CHKSUM] = 0; for (i=HEADLEN; i<allDataLen; i++) { snd_buf[CHKSUM] += snd_buf[i]; //printf("chksum:0x%02x data:0x%02x\n", snd_buf[CHKSUM], snd_buf[i]); } //printf("send [0x%02x%02x%02x%02x 0x%02x%02x%02x%02x 0x%02x%02x%02x%02x 0x%02x%02x%02x%02x\n", // printf("send [0x%02x%02x%02x%02x 0x%02x%02x%02x%02x 0x%02x%02x%02x%02x\n", // snd_buf[0], snd_buf[1], snd_buf[2], snd_buf[3], // head // snd_buf[4], snd_buf[5], snd_buf[6], snd_buf[7], // address // snd_buf[8], snd_buf[9], snd_buf[10], snd_buf[11]); // count //snd_buf[12], snd_buf[13], snd_buf[14], snd_buf[15]); // data tryTimes = 3; while (tryTimes > 0) { if (XS_SUCCESS == sendDataTty(fd, snd_buf, allDataLen)) break; tryTimes--; } if (0 == tryTimes) assert(0); tryTimes = 5; while (XS_SUCCESS == readPckHead(fd, rcv_buf) ) { if (BM_CMD_OK == rcv_buf[CMD]) { sentlen += sendlen; break; } else if (BM_CMD_ERR == rcv_buf[CMD]) { printf("send img error!"); break; } else { tryTimes--; } } } return 0; } static int sendRunCmd(int fd) { char snd_buf[HEADLEN+XS_ADDRESS_LEN] = {PKG_HEAD, BM_CMD_RUN, 0, PKG_TAIL}; int i, tryTimes, allDataLen; char rcv_buf[HEADLEN] = {0}; // address int2bytes(IMG_ADDRESS, snd_buf+HEADLEN); // chksum allDataLen = HEADLEN+XS_ADDRESS_LEN; snd_buf[CHKSUM] = 0; for (i=HEADLEN; i<allDataLen; i++) { snd_buf[CHKSUM] += snd_buf[i]; //printf("chksum:0x%02x data:0x%02x\n", snd_buf[CHKSUM], snd_buf[i]); } printf("send [0x%02x%02x%02x%02x 0x%02x%02x%02x%02x]\n", snd_buf[0], snd_buf[1], snd_buf[2], snd_buf[3], // head snd_buf[4], snd_buf[5], snd_buf[6], snd_buf[7]); // address tryTimes = 3; while (tryTimes > 0) { if (XS_SUCCESS == sendDataTty(fd, snd_buf, allDataLen)) break; tryTimes--; } if (0 == tryTimes) assert(0); tryTimes = 5; while (XS_SUCCESS == readPckHead(fd, rcv_buf) ) { if (BM_CMD_OK == rcv_buf[CMD]) { break; } else if (BM_CMD_ERR == rcv_buf[CMD]) { XS_FAIL; } else { tryTimes--; break; } } return XS_SUCCESS; } int initXs5013(int fd, const char *mode) { int ret; char rcv_buf[HEADLEN]; while (1) { if (XS_SUCCESS == readPckHead(fd, rcv_buf) ) { printf("recv package head [0x%02x%02x%02x%02x]\n", rcv_buf[STX], rcv_buf[CMD], rcv_buf[CHKSUM], rcv_buf[ETX]); if (BM_CMD_NOTIFY != rcv_buf[CMD]) { printf("incorrect command %d\n", rcv_buf[CMD]); } else { sendNoDataCmd(fd, BM_CMD_DEBUG); usleep(100*1000); exeCmdDLoad(fd, mode); sendRunCmd(fd); //printf("xs5013 is ready\n"); break; } } else { return -1; } } return 0; } int main(int argc, char** argv) { char *format = NULL; int fd = 0; char buf[100] = {0}; int tryTimes; char c; if (argc < 2) { printf(" no parameter -- read serial\n"); printf(" para1: command\n"); printf(" ahd/cvi/tvi/pattern -- download img\n"); printf(" 720p25 -- switch video format\n"); printf(" 720p30 -- switch video format\n"); printf(" 720p50 -- switch video format\n"); printf(" 720p60 -- switch video format\n"); printf(" 1080p25 -- switch video format\n"); printf(" 1080p30 -- switch video format\n"); printf(" 1080p50 -- switch video format, only for cvi\n"); printf(" 1080p60 -- switch video format, only for cvi\n"); printf(" 720pal -- switch video format, 720x576-50\n"); printf(" 720n -- switch video format, 720x480-60\n\n"); printf(" ex: xs5013 ahd\n\n"); return 0; } fd = open(TTY_NAME, O_RDWR | O_NOCTTY | O_NDELAY); if (-1 == fd) { perror("Can't Open Serial Port"); return (-1); } setOpt(fd); if (argc >= 2 ) { if (0 == strcmp("ahd", argv[1]) ||0 == strcmp("cvi", argv[1]) || 0 == strcmp("tvi", argv[1]) || 0 == strcmp("pattern", argv[1]) ) { int ret = initXs5013(fd, argv[1]); if (argc == 2) { if (0 != ret) return -1; } else { printf("init %s\n", argv[2]); sprintf(buf, "%s\r", argv[2]); sendDataTty(fd, buf, strlen(buf)); printf("init %s end\n", argv[2]); } } else { printf("switch %s\n", argv[1]); sprintf(buf, "%s\r", argv[1]); sendDataTty(fd, buf, strlen(buf)); } } tryTimes = 1024; while (tryTimes--) { if (1 == readbytes(fd, &c, 1)) { if (isprint(c) || iscntrl(c)) { putchar(c); } else { printf("0x%02x\n", c); } } else { break; } if ('#' == c || '$' == c) { putchar('\n'); break; } } close (fd); return 0; }
版本包说明:
1.版本名称:miniboot_reload_xs5013.tgz,linux环境下解压后使用。
2.版本包的组成
release
|-miniboot_reload_xs5013_ahd.img
|-miniboot_reload_xs5013_cvi.img
|-miniboot_reload_xs5013_tvi.img
3.每个镜像文件包含的分辨率以及启动命令如下:(分辨率描述说明:宽x高-帧率)
1)ahd (对应的镜像:miniboot_reload_xs5013_ahd.img)
1.分辨率:1280x720-25 串口启动命令:720p25
2.分辨率:1280x720-30 串口启动命令:720p30
3.分辨率:1280x720-50 串口启动命令:720p50 (未验证)
4.分辨率:1280x720-60 串口启动命令:720p60
5.分辨率:1920x1080-25 串口启动命令:1080p25
6.分辨率:1920x1080-30 串口启动命令:1080p30
2)cvi (对应的镜像:miniboot_reload_xs5013_cvi.img)
1.分辨率:1280x720-25 串口启动命令:720p25
2.分辨率:1280x720-30 串口启动命令:720p30
3.分辨率:1280x720-50 串口启动命令:720p50
4.分辨率:1280x720-60 串口启动命令:720p60
5.分辨率:1920x1080-25 串口启动命令:1080p25
6.分辨率:1920x1080-30 串口启动命令:1080p30
7.分辨率:1920x1080-50 串口启动命令:1080p50 (未验证)
8.分辨率:1920x1080-60 串口启动命令:1080p60 (未验证)
3)tvi (对应的镜像:miniboot_reload_xs5013_tvi.img)
1.分辨率:1280x720-25 串口启动命令:720p25
2.分辨率:1280x720-30 串口启动命令:720p30
3.分辨率:1280x720-50 串口启动命令:720p50
4.分辨率:1280x720-60 串口启动命令:720p60
5.分辨率:1920x1080-25 串口启动命令:1080p25
6.分辨率:1920x1080-30 串口启动命令:1080p30
4)cvbs (该模式没有单独的镜像文件,在ahd/cvi/tvi三个镜像中均存在)
1.分辨率:720x576-50 串口启动命令:720pal
2.分辨率:720x480-60 串口启动命令:720n
5)系统复位 (该模式没有单独的镜像文件,在ahd/cvi/tvi三个镜像中均存在)
1.分辨率:支持所有分辨率 串口启动命令:reset
烧写说明
1.烧写工具包:XS_CHIP_TOOLS_V1.4.8.rar,解压后使用。
2.使用说明,该工具适用于通过串口直接给xs5013进行烧写程序,如果是通过主控芯片来控制xs5013进行程序的烧写,需要客户按照《串口协议.pdf》中的介绍,自己开发主控的烧写程序。
//1920*1080@60(16:9)
rgb_timing0: timing0 {
clock-frequency = <148500000>; // 148.5MHz
hactive = <1920>;
vactive = <1080>;
hback-porch = <148>;
hfront-porch = <88>;
vback-porch = <36>;
vfront-porch = <4>;
hsync-len = <44>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//1920*1080@25(16:9)
rgb_timing0: timing1 {
clock-frequency = <74250000>; // 74.25MHz
hactive = <1920>;
vactive = <1080>;
hback-porch = <148>;
hfront-porch = <528>;
vback-porch = <36>;
vfront-porch = <4>;
hsync-len = <44>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//1920*1080@30(16:9)
rgb_timing0: timing2 {
clock-frequency = <74250000>; // 74.25MHz
hactive = <1920>;
vactive = <1080>;
hback-porch = <148>;
hfront-porch = <88>;
vback-porch = <36>;
vfront-porch = <4>;
hsync-len = <44>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//1280*720@60(16:9)
rgb_timing0: timing3 {
clock-frequency = <74250000>; // 74.25MHz
hactive = <1280>;
vactive = <720>;
hback-porch = <220>;
hfront-porch = <110>;
vback-porch = <20>;
vfront-porch = <5>;
hsync-len = <40>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//1280*720@50(16:9)
rgb_timing0: timing4 {
clock-frequency = <74250000>; // 74.25MHz
hactive = <1280>;
vactive = <720>;
hback-porch = <220>;
hfront-porch = <440>;
vback-porch = <20>;
vfront-porch = <5>;
hsync-len = <40>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//1280*720@30(16:9)
rgb_timing0: timing5 {
clock-frequency = <74250000>; // 74.25MHz
hactive = <1280>;
vactive = <720>;
hback-porch = <220>;
hfront-porch = <1760>;
vback-porch = <20>;
vfront-porch = <5>;
hsync-len = <40>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//1280*720@25(16:9)
rgb_timing0: timing6 {
clock-frequency = <74250000>; // 74.25MHz
hactive = <1280>;
vactive = <720>;
hback-porch = <220>;
hfront-porch = <2420>;
vback-porch = <20>;
vfront-porch = <5>;
hsync-len = <40>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//CVBS 720*480@60(4:3)
rgb_timing0: timing7 {
clock-frequency = <27000000>; // 27MHz
hactive = <720>;
vactive = <480>;
hback-porch = <60>;
hfront-porch = <16>;
vback-porch = <30>;
vfront-porch = <9>;
hsync-len = <62>;
vsync-len = <6>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
//CVBS 720*576@50(4:3)
rgb_timing0: timing8 {
clock-frequency = <27000000>; // 27MHz
hactive = <720>;
vactive = <576>;
hback-porch = <68>;
hfront-porch = <12>;
vback-porch = <39>;
vfront-porch = <5>;
hsync-len = <64>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
微信扫码关注
更新实时通知