在汽车液晶仪表中,指针旋转功能是一项重要需求。本文档主要介绍先楫使用6800系列通过LVDS协议驱动12.3英寸屏幕实现指针旋转的常用方法。
本文档测试使用的硬件平台有先楫HPM6800EVK开发板、屏幕为群创光电DJ123IA-01B。使用的SDK版本为sdk_env_v1.4.0。
图片切换来实现指针旋转
生成指针图像:本方法需提前将旋转过程中各个角度图片储存,然后依次切换图片,来模拟图片旋转的效果,使用ImageMagick(https://imagemagick.org/index.php)生成指针在不同角度的图像
不过这样一次只能生成一张旋转的图片,如果需要批量生成(每一度生成一张)需要使用脚本。在Window系统下保存文件为.ps1文件使用Powershell运行。
但生成的图片不能直接使用还需要转换成C语言数组格式。可以通过NXP的GUI-Guider软件或者使用LVGL官方的图像格式转换网址(https://lvgl.io/tools/imageconverter)生成。
不过这种方法对存储空间要求较大,把PNG/JPG的二进制文件转换成C语言数组格式后文件大小会比之前更大(每个字节会额外多出“0x”、“,”字符)。所以更适合那种只有几种变化形式的滑块动画。
b.更新图片缓冲区,刷新图片
将旋转后的图像数据复制到指针缓冲区
设置LCD的下一帧显示缓冲区:使用lcdc_layer_set_next_buffer函数,指定层2的下一个显示缓冲区地址为Pointerbuffer的地址。通过core_local_mem_to_sys_address函数将本地地址转换为系统地址,以确保LCD控制器能够正确访问该缓冲区。
刷新图层:
直接对图像中的像素点进行旋转计算
本方法是直接将旋转后的像素坐标计算出来,旋转矩阵计算的方法精度高,不会失真。但计算量大对于主频要求较高。
首先需要找到图像中心点,将旋转角度从度数转换为弧度,然后计算该角度的正弦值和余弦值。然后逐行逐列地遍历图像中的每个像素。
同时需要满足两个条件:1.旋转后在原图像范围外的部分不能影响其他图层。2.旋转后原图像空缺的部分要保持透明
将旋转后的图像数据复制到图层的缓冲区,然后刷新图层就能达到图片旋转的效果。这种方法对存储空间要求不高,只需要一张初始的角度的指针图片,但对于主频要求较高。
以旋转一张1920x720分辨率的图像为例,每一个像素坐标分为四部分(RGBA)。三原色占比和透明度。每个计算后的坐标都要检查是否在原图像范围内,然后将旋转后的图像数据复制到新的位置。
LVGL 图形库旋转指针
LVGL是一个免费开源嵌入式图形库,先楫有官方移植的LVGL工程模板。通过 lvgl.img_set_angle 可以对图片进行旋转,使用的单位是 角度值*10,方向是顺时针, 100 就表示 10 度。
使用lv_anim_set_values(&img, 0, 2800);可以将图片从0度旋转到280度.并达到动画效果。使用LVGL显示图片需要注意,转换图片为C语言数组必须用官方的图像格式转换网址(https://lvgl.io/tools/imageconverter)
- 声明并初始化动画对象。
- 绑定动画到图像对象 fg_img。
- 设置回调函数 set_angle,在动画执行过程中更新图像的角度。
- 设置动画值范围为从 0 到 2500。
- 设置动画持续时间为 25 秒。
- 设置动画为无限重复。
- 启动动画。
使用LVGL的img_set_angle来旋转图片效率要比直接计算图片像素效率稍高。以本文使用的指针的图片为例,旋转564x564的图片,直接计算像素坐标来旋转280度需要27秒,如果使用img_set_angle旋转差不多只需要23秒左右。
使用LVGL旋转图片相对来说比较简单,只需要调用API就能实现。减少了手动处理边界检查和处理超出范围像素的工作量,并且LVGL 利用内部优化算法使图片旋转效率更高。
先楫68系列有支持2D图形加速PDMA,支持两个图层的独立旋转,不过只能按固定角度旋转,所以不太适用于指针旋转的场景。
硬件VG_lite旋转指针
先楫68系列支持Open VG GPU,可实现两个图层的处理,支持任意角度的旋转。这个方法从原理上能够实现指针旋转,不过本文方法在有些细节上没有处理好,旋转后屏幕会花屏。
首先需要调用vg_lite_translate对矩阵进行平移变换,确定旋转中心。VG_LITE_NORMAL_IMAGE_MODE
VG_LITE_NORMAL_IMAGE_MODE使用普通渲染模式,除此之外还有混合模式,禁用模式等。
VG_lite旋转指针最关键的函数是vg_lite_rotate(rAngle, &matrix);这个函数并不会直接旋转图片,而是计算旋转角度得到了一个旋转矩阵。由于是导入外部的图片而不是直接绘制,所以需要额外通过vg_lite_blit函数用于将一个缓冲区上的内容应用matrix矩阵绘制到另一个缓冲区上。
NXP的i.MX RT 系列的图形编程应用文档(https://www.nxp.com/docs/zh/application-note/AN14210.pdf)中也有讲述VG_lite图片旋转的方法,虽然那篇教程使用的函数是NXP自己封装的,不是VGLite官方的API,但是也有很高的参考价值。