首先,致谢微凉大侠的工作,让驱动TVD模块,得以成为可能。
分享F1C100S的TVD源码,TVIN0接CVBS摄像头采集数据显示到LCD屏
https://whycan.com/t_5612.html
经过两天的研究,搜遍整个互联网,综合所有能找到的资料,编写了一个TVD驱动,虽然不完美,还有很多坑,但还是在这里总结下,避免后人重复踩坑。
1,首先是修改pll video时钟,因为TVD模块需要使用27MHZ,这里一般需要将pll设为297MHZ, 但因为需要兼容某些屏幕,这个时钟偏低,重新计算了一个时钟378MHZ,这个也可以方便的分频出27MHZ出来。
2,关于TVD寄存器,这个全志是完全没有释放出来,我这里找到了D1手册,还有F133手册里有TVD的相关说明,虽然完全对不上,但可以用来理解TVD模块,然后有针对性的去找参考。
3,实验平台采用歪朵拉r3,这个硬件上应该存在异常,我这边测试时,去掉了R30这个75欧匹配电组,不然完全找不到信号,一直蓝屏,还有一个需要注意的,CVBS的地也不能接,如果接了,就白屏,验证过,不是驱动的亮度设置问题,即使设成亮度最低,也一样白屏。怀疑要么是我信号源问题,要么是歪朵拉硬件问题。
4,检测外部信号的制式,在初始化后,需要做个延时,大概100ms不然无法正常检测。
5,现在驱动里,做了制式的判断,PAL制720X576,NTSC制720X480, YUV为常用的NV12格式。通过video_frame_to_argb函数可以很方便的转成RGB
6,现在显示效果不太好,怀疑是我这边环境问题,感兴趣的可以测试下。
测试方法:
1,使用歪朵拉的R3,去掉R30这个电阻,接入CVBS信号,不共地。
2,编译源码,见https://gitee.com/xboot/xboot/blob/master/src/arch/arm32/mach-f1c200s/README-zh-CN.md
3, 打开白盒测试选项,在Makefile中的CFG_WBOXTEST ?= n 改成y就行
4,启动程序,进入命令行后,键入 wboxtest camera preview命令即可在屏幕上看到图像,屏幕为5寸800x480 rgb接口通用屏幕。
驱动文件路径
https://gitee.com/xboot/xboot/blob/master/src/arch/arm32/mach-f1c200s/driver/cam-f1c200s-tvd.c
演示视频
欢迎大家继续研究TVD模块,全志的TVD模块技术上比较先进,自动增益控制,3D梳状滤波器,对比度,饱和度,亮度,都可以调节,3D滤波器需要4M的内存,貌似有点大。
离线
补充一个命令,如果你想用CVBS摄像头来扫描二维码,则只需执行如下命令,就可以扫描二维码了
wboxtest camera qrcode
离线
赞,显示效果上个月又调试了一下,发现有个寄存器需要调下,锯齿效果会好很多,晚点发出来
离线
赞,显示效果上个月又调试了一下,发现有个寄存器需要调下,锯齿效果会好很多,晚点发出来
TVD_REG_BASE+0x001c 这个寄存器的bit0 要等于0.原来初始化写的0x0087002f改成0x0087002a 显示效果好很多
离线
微凉VeiLiang 说:赞,显示效果上个月又调试了一下,发现有个寄存器需要调下,锯齿效果会好很多,晚点发出来
TVD_REG_BASE+0x001c 这个寄存器的bit0 要等于0.原来初始化写的0x0087002f改成0x0087002a 显示效果好很多
已参考你的BoloRTT里面的配置,这个bit已设为0了,现在我这边环境应该有点问题,现在没能找到带有全志参考电路的板子,没办法进一步确认显示效果。
不知哪位同学有这种板子,可以测试下,看看效果,怎么样,荔枝派,歪朵拉,都是没有的这种电路的。
离线
按全志参考电路的板子,接的模拟摄像头,信号和地都接上的。效果如下:
离线
按全志参考电路的板子,接的模拟摄像头,信号和地都接上的。效果如下:https://whycan.com/files/members/2190/微信图片_20210718161821.jpg
效果看起来还不错,估计还是歪朵拉没有按参考电路设计的问题,信号源出问题的概率太低,只有可能是这个原因了。
离线
按全志参考电路的板子,接的模拟摄像头,信号和地都接上的。效果如下:https://whycan.com/files/members/2190/微信图片_20210718161821.jpg
这个效果看着很好了啊!
大赞啊,能分享下如何配置的吗
离线
@xboot
大佬,调饱和度和对比度对应的寄存器是哪两个,找了很久都没找到资料
离线
看驱动代码
https://gitee.com/xboot/xboot/blob/master/src/arch/arm32/mach-f1c200s/driver/cam-f1c200s-tvd.c
case 0xd5d73dfe: /* "camera-set-saturation" */
if(p)
{
f1c200s_tvd_set_saturation(pdat, *p);
return 0;
}
break;
case 0x0ed48a72: /* "camera-get-saturation" */
if(p)
{
*p = f1c200s_tvd_get_saturation(pdat);
return 0;
}
break;
case 0xdae4842d: /* "camera-set-brightness" */
if(p)
{
f1c200s_tvd_set_brightness(pdat, *p);
return 0;
}
break;
case 0x13e1d0a1: /* "camera-get-brightness" */
if(p)
{
*p = f1c200s_tvd_get_brightness(pdat);
return 0;
}
break;
case 0xf3916322: /* "camera-set-contrast" */
if(p)
{
f1c200s_tvd_set_contrast(pdat, *p);
return 0;
}
break;
case 0xa8290296: /* "camera-get-contrast" */
if(p)
{
*p = f1c200s_tvd_get_contrast(pdat);
return 0;
}
break;
离线
找到了,多谢大佬
离线
@xboot
大佬,调不了显示分辨率的吗,我的LCD是800*600的,显示出来的效果不全,看你的效果也是两边没显示全
把初始化函数f1c100s_tvd_init中的width改成800,height改成600:
struct cam_f1c100s_tvd_pdata_t {
virtual_addr_t virt;
char * clk;
int irq;
int reset;
int channel;
//unsigned char yc[720 * 576 * 2];
unsigned char yc[800 * 600 * 2];
enum video_format_t fmt;
int width;
int height;
int buflen;
int ready;
};
......
s = f1c100s_tvd_get_source(pdat);
if(s == TVD_SOURCE_NTSC)
{
pdat->fmt = VIDEO_FORMAT_NV12;
pdat->width = 720;
pdat->height = 480;
pdat->buflen = pdat->width * pdat->height * 2;
pdat->ready = 0;
f1c100s_tvd_config(pdat, s, TVD_PL_YUV420);
f1c100s_tvd_set_fmt(pdat, TVD_PL_YUV420);
f1c100s_tvd_set_addr(pdat, &pdat->yc[0], &pdat->yc[pdat->width * pdat->height]);
}
else if(s == TVD_SOURCE_PAL)
{
pdat->fmt = VIDEO_FORMAT_NV12;
//pdat->width = 720;
//pdat->height = 576;
pdat->width = 800;
pdat->height = 600;
pdat->buflen = pdat->width * pdat->height * 2;
pdat->ready = 0;
f1c100s_tvd_config(pdat, s, TVD_PL_YUV420);
f1c100s_tvd_set_fmt(pdat, TVD_PL_YUV420);
f1c100s_tvd_set_addr(pdat, &pdat->yc[0], &pdat->yc[pdat->width * pdat->height]);
}
f1c100s_tvd_set_blue(pdat, 2);
f1c100s_tvd_capture_off(pdat);
f1c100s_tvd_irq_clear(pdat);
f1c100s_tvd_irq_disable(pdat);
显示就不正常了:
把draw_preview函数里面的width和height改成800和600:
pdat->s->width = 800;
pdat->s->height = 600;
matrix_init_translate(&m, (surface_get_width(s) - surface_get_width(pdat->s)) / 2, (surface_get_height(s) - surface_get_height(pdat->s)) / 2);
surface_blit(s, NULL, &m, pdat->s, RENDER_TYPE_GOOD);
显示效果只是移了一下位置
最近编辑记录 岁月快快快 (2022-01-08 16:29:35)
离线
修改 matrix参数进行仿射变换,想做啥效果都可以,移位,缩放,旋转,镜像。。。。想怎么来就怎么来。
离线
贴一段xui里矩阵操作代码吧,4种填充模式。
switch(opt & (0x3 << 12))
{
case XUI_IMAGE_NONE:
sx = 1.0;
sy = 1.0;
break;
case XUI_IMAGE_CONTAIN:
sx = (double)r->w / (double)surface_get_width(s);
sy = (double)r->h / (double)surface_get_height(s);
if(sx >= sy)
sx = sy;
else
sy = sx;
break;
case XUI_IMAGE_COVER:
sx = (double)r->w / (double)surface_get_width(s);
sy = (double)r->h / (double)surface_get_height(s);
if(sx <= sy)
sx = sy;
else
sy = sx;
break;
case XUI_IMAGE_FILL:
sx = (double)r->w / (double)surface_get_width(s);
sy = (double)r->h / (double)surface_get_height(s);
break;
default:
sx = 1.0;
sy = 1.0;
break;
}
matrix_init_translate(&m, r->x + r->w / 2, r->y + r->h / 2);
if(angle != 0.0)
matrix_rotate(&m, angle);
matrix_translate(&m, -surface_get_width(s) / 2 * sx, -surface_get_height(s) / 2 * sy);
matrix_scale(&m, sx, sy);
离线
具体4种模式,参考css里面的objtct-fit。
===============================================
object-fit:指定可替换元素的内容应该如何适应到其使用的高度和宽度确定的框。与我们熟悉的background-size属性有点相似。
contain被替换的内容将被缩放,以在填充元素的内容框时保持其宽高比。 整个对象在填充盒子的同时保留其长宽比,因此如果宽高比与框的宽高比不匹配,该对象将被添加“黑边”。
cover被替换的内容在保持其宽高比的同时填充元素的整个内容框。如果对象的宽高比与内容框不相匹配,该对象将被剪裁以适应内容框。
fill被替换的内容正好填充元素的内容框。整个对象将完全填充此框。如果对象的宽高比与内容框不相匹配,那么该对象将被拉伸以适应内容框。
none被替换的内容将保持其原有的尺寸。
scale-down内容的尺寸与 none 或 contain 中的一个相同,取决于它们两个之间谁得到的对象尺寸会更小一些。
离线
搞定了,多谢大佬
缩放进行了浮点运算,画面没有之前流畅了
最近编辑记录 岁月快快快 (2022-01-13 11:49:26)
离线
@xboot
大佬,画面的反应速度有点慢,有什么办法提高显示画面的速度吗,还有一个就是调用matrix_scale进行缩放之后,因为进行了浮点运算,
画面显示的速度更慢了(f1c100s好像没有硬浮点)
,除了这个办法还有其它办法把图像扩充到全屏吗;摄像头移动的时候,画面有撕裂线(像波浪一样),是因为没开双缓冲的原因吗
最近编辑记录 岁月快快快 (2022-02-11 14:15:15)
离线
没有垂直同步,如果你仅预览,建议将TVIN的格式转换后的buffer直接作为LCD的显示buffer吧,这样可以避免拷贝,当然最好能用上DE,FE这种硬件模块,效率更高
离线
是否可以将 CVBS 输出用作标准 DAC?另外在我看来,如果 XBOOT 也有 Micropython 解释器,那就太好了。
离线
摄像头到显示的延时有多少呢?有人测试过吗
离线
亲大侠们,怎么检测摄像头有没有接啊?读哪个寄存器?产品要求没接摄像头时输出蓝屏,但有条纹抖动,全屏显示时有雪花状,然后才蓝屏。我的是800*480,求助!
离线
微凉VeiLiang 说:赞,显示效果上个月又调试了一下,发现有个寄存器需要调下,锯齿效果会好很多,晚点发出来
TVD_REG_BASE+0x001c 这个寄存器的bit0 要等于0.原来初始化写的0x0087002f改成0x0087002a 显示效果好很多
请问下大侠,这个寄存器是什么意思呢,我在全志的D1S上驱动CVBS也有锯齿这个问题,不知道能否改寄存器也能否优化。
离线
@xboot
大神,请问下,CVBS有些锯齿,有什么办法吗??
跪求了
离线
@xboot
大神,请问下,CVBS有些锯齿,有什么办法吗??
跪求了
锯齿问题,是CVBS奇偶场引起的,需要用De-Interlace处理。但是在C100上如何使用,这又是另一个难题了...
好像要用到DE模块...搞不懂
离线
@godzhou0909
是裸奔的吗?我现在在T113平台山裸奔TVD,还有点小问题,估计又是寄存器配置了
离线
T113平台的效果是这样,NTSC格式的信号。
离线