02
2024
09

xs5013模拟视频编码,bt1120转ahd tvi cvi格式,调试资料和教程

可以帮忙调试,QQ:778292363

未命名码 (1).png

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格式。

SIN2O%W9]UT)7N2G$9VU$1P.png

SYFOSGYKATW8{9P{YB2B2SH.png


#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>;

     };

gzh

微信扫码关注

更新实时通知

« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。