联阳IT6801FN是HDMI转RGB/BT.1120桥接芯片,海思Hi3536 NVR芯片的Vin只支持BT.1120接口输入,因为Hi3536支持4K@30的编码,所以找到了IT6801FN,它支持行场内嵌、时钟双边沿采样、yuv422 16bit格式输出,刚好能对接海思芯片。当然也可以使用FPGA对接Hi3536,参考我另一篇文章《FPGA实现BT.1120编码》,实现了单边沿采样的BT.1120。
不用不知道,一用满是坑!官方提供的demo代码写得太乱了。其实像这种芯片没必要提供寄存器手册(你提供了又写得不够详细),应该代码写好点,封装成api接口让我们调用,方便使用才是顾客至上,这样我们还更愿意买你们的芯片!lattice公司的芯片有些是提供api接口的,譬如sii9777s、sii9396s等,不过多线程调用还是难用!
移植好官方提供的demo其实就可以正常使用了,但我使用IT6801过程中,发现它的图像质量不太好,没有ADV7604等ADI公司的好。
对于rgb转yuv422,0x67寄存器的bit0需要打开,可以滤波,改善图像质量:
觉得色彩不太好的话,可以尝试修改色彩空间转换公式:
这几个寄存器的值对应色彩空间转换方程的系数
#include <stdio.h>
struct coefficient
{
float fR;
float fG;
float fB;
int iOffset;
};
struct matrix_param
{
struct coefficient stY;
struct coefficient stCb;
struct coefficient stCr;
};
static int get_coefficient(float data, unsigned char* table)
{
unsigned short wtmp = 0;
float tmp = data * 2048;
if(tmp < 0)
{
tmp = 16384.0 + tmp;
}
wtmp = (unsigned short)(tmp + 0.5); //四舍五入
table[0] = wtmp&0xff;
table[1] = (wtmp>>8)&0x3f;
return 0;
}
static int get_matrix_table(struct matrix_param *pParam, unsigned char CscRegTab[21])
{
if(!pParam)
{
return -1;
}
CscRegTab[0] = pParam->stY.iOffset;
CscRegTab[1] = pParam->stCb.iOffset;
CscRegTab[2] = 0x10;
get_coefficient(pParam->stY.fG, &CscRegTab[3]);
get_coefficient(pParam->stY.fR, &CscRegTab[3 + 2]);
get_coefficient(pParam->stY.fB, &CscRegTab[3 + 4]);
get_coefficient(pParam->stCr.fG, &CscRegTab[3 + 6]);
get_coefficient(pParam->stCr.fR, &CscRegTab[3 + 8]);
get_coefficient(pParam->stCr.fB, &CscRegTab[3 + 10]);
get_coefficient(pParam->stCb.fG, &CscRegTab[3 + 12]);
get_coefficient(pParam->stCb.fR, &CscRegTab[3 + 14]);
get_coefficient(pParam->stCb.fB, &CscRegTab[3 + 16]);
return 0;
}
static void printMatrix(unsigned char CscRegTab[21])
{
int i = 0;
for(i = 0; i < 21; i++)
{
if(!i || i%2)
{
printf(" ");
}
printf("0x%x, ", CscRegTab[i]);
if((i == 2) || (i == 8) || (i == 14) || (i == 20))
{
printf("\n");
}
}
printf("\n");
}
int main(void)
{
unsigned char CscRegTab[21] = {0};
struct matrix_param stMatrix= {0};
/**
Y709 = 0.715G + 0.213R + 0.072B + 0
Cr = -0.464G + 0.511R + -0.047B + 128
Cb = -0.394G + -0.117R + 0.511B + 128
*/
stMatrix.stY.fR = 0.213;
stMatrix.stY.fG = 0.715;
stMatrix.stY.fB = 0.072;
stMatrix.stY.iOffset = 0;
stMatrix.stCr.fR = 0.511;
stMatrix.stCr.fG = -0.464;
stMatrix.stCr.fB = -0.047;
stMatrix.stCr.iOffset = 128;
stMatrix.stCb.fR = -0.117;
stMatrix.stCb.fG = -0.394;
stMatrix.stCb.fB = 0.511;
stMatrix.stCb.iOffset = 128;
get_matrix_table(&stMatrix, CscRegTab);
printMatrix(CscRegTab);
return 0;
}
上面的tool可打印出矩阵列表,bCSCMtx_RGB2YUV_ITU709_16_235:
//以下代码均摘抄自官方demo
static void chgbank(int bank)
{
hdmirxset(0x0F, 0x03, bank&3); //i2c写接口,0x03是掩码,只对0xf寄存器的bit0和bit1操作,其他位不变,可参考官方demo代码
}
const static unsigned char bCSCMtx_RGB2YUV_ITU709_16_235[]=
{
0x00, 0x80, 0x10,
0xB8, 0x05, 0xB4, 0x01, 0x94,0x00,
0x4A, 0x3C, 0x17, 0x04, 0x9F,0x3F,
0xD9, 0x3C, 0x10, 0x3F, 0x17,0x04
};
// 设置CSC矩阵Reg170 ~ Reg184
chgbank(1);
hdmirxbwr(REG_RX_170,
sizeof(bCSCMtx_RGB2YUV_ITU709_16_235),
bCSCMtx_RGB2YUV_ITU709_16_235);
chgbank(0);
hdmirxwr(REG_RX_067, 0x80 | B_RX_EN_UDFILTER); //RGB24 to YUV422 need up/dn filter.
值得注意的是,上述RGB转yuv公式指的是RGB转yuv4:4:4,因为每一个RGB点均对应一对u、v值。
最后得出结论,IT6801FN还是不用为好!!! 最后发现图像质量是Hi3536的VI引起的,跟IT6801FN无关。