06_HDMI 显示器驱动设计与验证

06_HDMI 显示器驱动设计与验证

  • 1. HDMI 接口及引脚定义
    • 1.1 HDMI A Type 接口引脚图
    • 1.2 HDMI A Type 接口引脚定义
  • 2. HDMI 原理
    • 2.1 HDMI 显示原理
    • 2.2 TMDS 传输原理
  • 3. 实验目标
  • 4. 程序框图
    • 4.1 顶层模块
    • 4.2 时钟生成模块
    • 4.3 HDMI 驱动控制模块
      • 4.3.1 第一个步骤
      • 4.3.2 编码模块参考流程图
      • 4.3.3 第二个步骤
      • 4.3.4 ALTDDIO_OUT IP 核框图
      • 4.3.5 控制模块
  • 5. RTL
    • 5.1 encode
    • 5.2 hdmi_ctrl
    • 5.3 par_to_ser
    • 5.4 hdmi_colorbar
  • 6. Testbench

1. HDMI 接口及引脚定义

1.1 HDMI A Type 接口引脚图

在这里插入图片描述

1.2 HDMI A Type 接口引脚定义

在这里插入图片描述
在这里插入图片描述

2. HDMI 原理

2.1 HDMI 显示原理

在这里插入图片描述

2.2 TMDS 传输原理

在这里插入图片描述
输出的是差分信号, 都是一对一对的
要经过编码和串并转换
25MHZ 下 一个时钟周期是 8 bit 的并行数据,再此刻时钟下 要经过编码 变成 10 bit 数据。然后10 bit 数据要再此时钟下进行串行数据的转换。 则需要 10 * 25 = 250 MHZ 的时钟,因为 并串转换 是上升沿和下降沿都可以 所以需要 125 MHZ 即可。

需要 2 步

  1. 8->10 编码
  2. 10 差分 串
    在这里插入图片描述

3. 实验目标

实验目标:编写 HDMI 驱动,使用 FPGA 开发板驱动 HDMI 显示器显示十色等宽彩条, HDMI 显示模式为 640*480@60。
在这里插入图片描述

4. 程序框图

4.1 顶层模块

在这里插入图片描述
Rgb 是 565 rgb 是888

4.2 时钟生成模块

HDMI 显示模式为 640*480@60,时钟频率为 25MHz,而板卡晶振传入时钟频率为 50MHz。时钟生成模块的作用就是将 50MHz 晶振时钟分频为 25MHz 的 HDMI 工作时钟;除此之外,还要生成25MHz 时钟的 5 倍频 125MHz 时钟,125MHz 时钟的具体用途会在后文讲到。
在这里插入图片描述

4.3 HDMI 驱动控制模块

4.3.1 第一个步骤

编码
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.3.2 编码模块参考流程图

在这里插入图片描述
在这里插入图片描述

4.3.3 第二个步骤

串并转换
在这里插入图片描述

在这里插入图片描述

4.3.4 ALTDDIO_OUT IP 核框图

ALTDDIO_OUT IP 核接口信号描述
在这里插入图片描述
ALTDDIO_OUT IP 核时序图
在这里插入图片描述
ALTDDIO_OUT IP 核框图

4.3.5 控制模块

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5. RTL

5.1 encode

`timescale  1ns/1ns
module  encode
(input   wire            sys_clk     ,   //时钟信号input   wire            sys_rst_n   ,   //复位信号,低有效input   wire    [7:0]   data_in     ,   //输入8bit待编码数据input   wire            c0          ,   //控制信号c0input   wire            c1          ,   //控制信号c1input   wire            de          ,   //使能信号output  reg     [9:0]   data_out        //输出编码后的10bit数据
);//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter   DATA_OUT0   =   10'b1101010100,DATA_OUT1   =   10'b0010101011,DATA_OUT2   =   10'b0101010100,DATA_OUT3   =   10'b1010101011;//wire  define
wire            condition_1 ;   //条件1
wire            condition_2 ;   //条件2
wire            condition_3 ;   //条件3
wire    [8:0]   q_m         ;   //第一阶段转换后的9bit数据//reg   define
reg     [3:0]   data_in_n1  ;   //待编码数据中1的个数
reg     [7:0]   data_in_reg ;   //待编码数据打一拍
reg     [3:0]   q_m_n1      ;   //转换后9bit数据中1的个数
reg     [3:0]   q_m_n0      ;   //转换后9bit数据中0的个数
reg     [4:0]   cnt         ;   //视差计数器,0-1个数差别,最高位为符号位
reg             de_reg1     ;   //使能信号打一拍
reg             de_reg2     ;   //使能信号打两拍
reg             c0_reg1     ;   //控制信号c0打一拍
reg             c0_reg2     ;   //控制信号c0打两拍
reg             c1_reg1     ;   //控制信号c1打一拍
reg             c1_reg2     ;   //控制信号c1打两拍
reg     [8:0]   q_m_reg     ;   //q_m信号打一拍//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//data_in_n1:待编码数据中1的个数
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_in_n1  <=  4'd0;elsedata_in_n1  <=  data_in[0] + data_in[1] + data_in[2]+ data_in[3] + data_in[4] + data_in[5]+ data_in[6] + data_in[7];//data_in_reg:待编码数据打一拍
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_in_reg <=  8'b0;elsedata_in_reg <=  data_in;//condition_1:条件1
assign  condition_1 = ((data_in_n1 > 4'd4) || ((data_in_n1 == 4'd4)&& (data_in_reg[0] == 1'b0)));//q_m:第一阶段转换后的9bit数据
assign q_m[0] = data_in_reg[0];
assign q_m[1] = (condition_1) ? (q_m[0] ^~ data_in_reg[1]) : (q_m[0] ^ data_in_reg[1]);
assign q_m[2] = (condition_1) ? (q_m[1] ^~ data_in_reg[2]) : (q_m[1] ^ data_in_reg[2]);
assign q_m[3] = (condition_1) ? (q_m[2] ^~ data_in_reg[3]) : (q_m[2] ^ data_in_reg[3]);
assign q_m[4] = (condition_1) ? (q_m[3] ^~ data_in_reg[4]) : (q_m[3] ^ data_in_reg[4]);
assign q_m[5] = (condition_1) ? (q_m[4] ^~ data_in_reg[5]) : (q_m[4] ^ data_in_reg[5]);
assign q_m[6] = (condition_1) ? (q_m[5] ^~ data_in_reg[6]) : (q_m[5] ^ data_in_reg[6]);
assign q_m[7] = (condition_1) ? (q_m[6] ^~ data_in_reg[7]) : (q_m[6] ^ data_in_reg[7]);
assign q_m[8] = (condition_1) ? 1'b0 : 1'b1;//q_m_n1:转换后9bit数据中1的个数
//q_m_n0:转换后9bit数据中0的个数
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)beginq_m_n1  <=  4'd0;q_m_n0  <=  4'd0;endelsebeginq_m_n1  <=  q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7];q_m_n0  <=  4'd8 - (q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]);end//condition_2:条件2
assign  condition_2 = ((cnt == 5'd0) || (q_m_n1 == q_m_n0));//condition_3:条件3
assign  condition_3 = (((~cnt[4] == 1'b1) && (q_m_n1 > q_m_n0))|| ((cnt[4] == 1'b1) && (q_m_n0 > q_m_n1)));//数据打拍,为了各数据同步
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)beginde_reg1 <=  1'b0;de_reg2 <=  1'b0;c0_reg1 <=  1'b0;c0_reg2 <=  1'b0;c1_reg1 <=  1'b0;c1_reg2 <=  1'b0;q_m_reg <=  9'b0;endelsebeginde_reg1 <=  de;de_reg2 <=  de_reg1;c0_reg1 <=  c0;c0_reg2 <=  c0_reg1;c1_reg1 <=  c1;c1_reg2 <=  c1_reg1;q_m_reg <=  q_m;end//data_out:输出编码后的10bit数据
//cnt:视差计数器,0-1个数差别,最高位为符号位
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)begindata_out    <=  10'b0;cnt         <=  5'b0;endelsebeginif(de_reg2 == 1'b1)beginif(condition_2 == 1'b1)begindata_out[9]     <=  ~q_m_reg[8]; data_out[8]     <=  q_m_reg[8]; data_out[7:0]   <=  (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0];cnt <=  (~q_m_reg[8]) ? (cnt + q_m_n0 - q_m_n1) : (cnt + q_m_n1 - q_m_n0);endelsebeginif(condition_3 == 1'b1)begindata_out[9]     <= 1'b1;data_out[8]     <= q_m_reg[8];data_out[7:0]   <= ~q_m_reg[7:0];cnt <=  cnt + {q_m_reg[8], 1'b0} + (q_m_n0 - q_m_n1);endelsebegindata_out[9]     <= 1'b0;data_out[8]     <= q_m_reg[8];data_out[7:0]   <= q_m_reg[7:0];cnt <=  cnt - {~q_m_reg[8], 1'b0} + (q_m_n1 - q_m_n0);endendendelsebegincase    ({c1_reg2, c0_reg2})2'b00:  data_out <= DATA_OUT0;2'b01:  data_out <= DATA_OUT1;2'b10:  data_out <= DATA_OUT2;default:data_out <= DATA_OUT3;endcasecnt <=  5'b0;endendendmodule

5.2 hdmi_ctrl

`timescale  1ns/1ns
module  hdmi_ctrl
(input   wire            clk_1x      ,   //输入系统时钟input   wire            clk_5x      ,   //输入5倍系统时钟input   wire            sys_rst_n   ,   //复位信号,低有效input   wire    [7:0]   rgb_blue    ,   //蓝色分量input   wire    [7:0]   rgb_green   ,   //绿色分量input   wire    [7:0]   rgb_red     ,   //红色分量input   wire            hsync       ,   //行同步信号input   wire            vsync       ,   //场同步信号input   wire            de          ,   //使能信号output  wire            hdmi_clk_p  ,output  wire            hdmi_clk_n  ,   //时钟差分信号output  wire            hdmi_r_p    ,output  wire            hdmi_r_n    ,   //红色分量差分信号output  wire            hdmi_g_p    ,output  wire            hdmi_g_n    ,   //绿色分量差分信号output  wire            hdmi_b_p    ,output  wire            hdmi_b_n        //蓝色分量差分信号
);//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
wire    [9:0]   red     ;   //8b转10b后的红色分量
wire    [9:0]   green   ;   //8b转10b后的绿色分量
wire    [9:0]   blue    ;   //8b转10b后的蓝色分量//********************************************************************//
//**************************** Instantiate ***************************//
//********************************************************************//
//------------- encode_inst0 -------------
encode  encode_inst0
(.sys_clk    (clk_1x     ),.sys_rst_n  (sys_rst_n  ),.data_in    (rgb_blue   ),.c0         (hsync      ),.c1         (vsync      ),.de         (de         ),.data_out   (blue       )
);//------------- encode_inst1 -------------
encode  encode_inst1
(.sys_clk    (clk_1x     ),.sys_rst_n  (sys_rst_n  ),.data_in    (rgb_green  ),.c0         (hsync      ),.c1         (vsync      ),.de         (de         ),.data_out   (green      )
);//------------- encode_inst2 -------------
encode  encode_inst2
(.sys_clk    (clk_1x     ),.sys_rst_n  (sys_rst_n  ),.data_in    (rgb_red    ),.c0         (hsync      ),.c1         (vsync      ),.de         (de         ),.data_out   (red        )
);//------------- par_to_ser_inst0 -------------
par_to_ser  par_to_ser_inst0
(.clk_5x      (clk_5x    ),.par_data    (blue      ),.ser_data_p  (hdmi_b_p  ),.ser_data_n  (hdmi_b_n  )
);//------------- par_to_ser_inst1 -------------
par_to_ser  par_to_ser_inst1
(.clk_5x      (clk_5x    ),.par_data    (green     ),.ser_data_p  (hdmi_g_p  ),.ser_data_n  (hdmi_g_n  )
);//------------- par_to_ser_inst2 -------------
par_to_ser  par_to_ser_inst2
(.clk_5x      (clk_5x    ),.par_data    (red       ),.ser_data_p  (hdmi_r_p  ),.ser_data_n  (hdmi_r_n  )
);//------------- par_to_ser_inst3 -------------
par_to_ser  par_to_ser_inst3
(.clk_5x      (clk_5x        ),.par_data    (10'b1111100000),.ser_data_p  (hdmi_clk_p    ),.ser_data_n  (hdmi_clk_n    )
);endmodule

5.3 par_to_ser

`timescale  1ns/1ns
module par_to_ser
(input   wire            clk_5x      ,   //输入系统时钟input   wire    [9:0]   par_data    ,   //输入并行数据output  wire            ser_data_p  ,   //输出串行差分数据output  wire            ser_data_n      //输出串行差分数据
);//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire  define
wire    [4:0]   data_rise = {par_data[8],par_data[6],par_data[4],par_data[2],par_data[0]};
wire    [4:0]   data_fall = {par_data[9],par_data[7],par_data[5],par_data[3],par_data[1]};//reg   define
reg     [4:0]   data_rise_s = 0;
reg     [4:0]   data_fall_s = 0;
reg     [2:0]   cnt = 0;always @ (posedge clk_5x)begincnt <= (cnt[2]) ? 3'd0 : cnt + 3'd1;data_rise_s  <= cnt[2] ? data_rise : data_rise_s[4:1];data_fall_s  <= cnt[2] ? data_fall : data_fall_s[4:1];end//********************************************************************//
//**************************** Instantiate ***************************//
//********************************************************************//
//------------- ddio_out_inst0 -------------
ddio_out    ddio_out_inst0
(.datain_h   (data_rise_s[0] ),.datain_l   (data_fall_s[0] ),.outclock   (~clk_5x        ),.dataout    (ser_data_p     )
);//------------- ddio_out_inst1 -------------
ddio_out    ddio_out_inst1
(.datain_h   (~data_rise_s[0]),.datain_l   (~data_fall_s[0]),.outclock   (~clk_5x        ),.dataout    (ser_data_n     )
);endmodule

5.4 hdmi_colorbar

`timescale  1ns/1ns
module  hdmi_colorbar
(input   wire            sys_clk     ,   //输入工作时钟,频率50MHzinput   wire            sys_rst_n   ,   //输入复位信号,低电平有效output  wire            ddc_scl     ,output  wire            ddc_sda     ,output  wire            tmds_clk_p  ,output  wire            tmds_clk_n  ,   //HDMI时钟差分信号output  wire    [2:0]   tmds_data_p ,output  wire    [2:0]   tmds_data_n     //HDMI图像差分信号
);//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire            vga_clk ;   //VGA工作时钟,频率25MHz
wire            clk_5x  ;
wire            locked  ;   //PLL locked信号
wire            rst_n   ;   //VGA模块复位信号
wire    [11:0]  pix_x   ;   //VGA有效显示区域X轴坐标
wire    [11:0]  pix_y   ;   //VGA有效显示区域Y轴坐标
wire    [15:0]  pix_data;   //VGA像素点色彩信息
wire            hsync   ;   //输出行同步信号
wire            vsync   ;   //输出场同步信号
wire    [15:0]  rgb     ;   //输出像素信息
wire            rgb_valid;//rst_n:VGA模块复位信号
assign  rst_n   = (sys_rst_n & locked);
assign  ddc_scl = 1'b1;
assign  ddc_sda = 1'b1;//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************////------------- clk_gen_inst -------------
clk_gen clk_gen_inst
(.areset     (~sys_rst_n ),  //输入复位信号,高电平有效,1bit.inclk0     (sys_clk    ),  //输入50MHz晶振时钟,1bit.c0         (vga_clk    ),  //输出VGA工作时钟,频率25Mhz,1bit.c1         (clk_5x     ),.locked     (locked     )   //输出pll locked信号,1bit
);//------------- vga_ctrl_inst -------------
vga_ctrl  vga_ctrl_inst
(.vga_clk    (vga_clk    ),  //输入工作时钟,频率25MHz,1bit.sys_rst_n  (rst_n      ),  //输入复位信号,低电平有效,1bit.pix_data   (pix_data   ),  //输入像素点色彩信息,16bit.pix_x      (pix_x      ),  //输出VGA有效显示区域像素点X轴坐标,10bit.pix_y      (pix_y      ),  //输出VGA有效显示区域像素点Y轴坐标,10bit.hsync      (hsync      ),  //输出行同步信号,1bit.vsync      (vsync      ),  //输出场同步信号,1bit.rgb_valid  (rgb_valid  ),.rgb        (rgb        )   //输出像素点色彩信息,16bit
);//------------- vga_pic_inst -------------
vga_pic vga_pic_inst
(.vga_clk    (vga_clk    ),  //输入工作时钟,频率25MHz,1bit.sys_rst_n  (rst_n      ),  //输入复位信号,低电平有效,1bit.pix_x      (pix_x      ),  //输入VGA有效显示区域像素点X轴坐标,10bit.pix_y      (pix_y      ),  //输入VGA有效显示区域像素点Y轴坐标,10bit.pix_data   (pix_data   )   //输出像素点色彩信息,16bit);//------------- hdmi_ctrl_inst -------------
hdmi_ctrl   hdmi_ctrl_inst
(.clk_1x      (vga_clk           ),   //输入系统时钟.clk_5x      (clk_5x            ),   //输入5倍系统时钟.sys_rst_n   (rst_n             ),   //复位信号,低有效.rgb_blue    ({rgb[4:0],3'b0}   ),   //蓝色分量.rgb_green   ({rgb[10:5],2'b0}  ),   //绿色分量.rgb_red     ({rgb[15:11],3'b0} ),   //红色分量.hsync       (hsync             ),   //行同步信号.vsync       (vsync             ),   //场同步信号.de          (rgb_valid         ),   //使能信号.hdmi_clk_p  (tmds_clk_p        ),.hdmi_clk_n  (tmds_clk_n        ),   //时钟差分信号.hdmi_r_p    (tmds_data_p[2]    ),.hdmi_r_n    (tmds_data_n[2]    ),   //红色分量差分信号.hdmi_g_p    (tmds_data_p[1]    ),.hdmi_g_n    (tmds_data_n[1]    ),   //绿色分量差分信号.hdmi_b_p    (tmds_data_p[0]    ),.hdmi_b_n    (tmds_data_n[0]    )    //蓝色分量差分信号
);endmodule

6. Testbench

`timescale  1ns/1ns
module  tb_hdmi_colorbar();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire  define
wire            ddc_scl     ;
wire            ddc_sda     ;
wire            tmds_clk_p  ;
wire            tmds_clk_n  ;
wire    [2:0]   tmds_data_p ;
wire    [2:0]   tmds_data_n ;//reg   define
reg             sys_clk     ;
reg             sys_rst_n   ;//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************////sys_clk,sys_rst_n初始赋值
initialbeginsys_clk     =   1'b1;sys_rst_n   <=  1'b0;#200sys_rst_n   <=  1'b1;end//sys_clk:产生时钟
always  #10 sys_clk = ~sys_clk  ;//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************////------------- hdmi_colorbar_inst -------------
hdmi_colorbar   hdmi_colorbar_inst
(.sys_clk     (sys_clk    ),   //输入工作时钟,频率50MHz.sys_rst_n   (sys_rst_n  ),   //输入复位信号,低电平有效.ddc_scl     (ddc_scl    ),.ddc_sda     (ddc_sda    ),.tmds_clk_p  (tmds_clk_p ),.tmds_clk_n  (tmds_clk_n ),   //HDMI时钟差分信号.tmds_data_p (tmds_data_p),.tmds_data_n (tmds_data_n)    //HDMI图像差分信号
);endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/22076.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

巩固一下NodeJs

1、初始化(确保当前电脑有node环境) npm init 2、安装express npm i expressnpm i ws文件结构 3、编写相关代码启动node服务(server.js) //导入下列模块&#xff0c;express搭建服务器&#xff0c;fs用来操作文件、ws用来实现webscoket const express require("expr…

vgg16-pytorch

基于pytorch实现VGG16模型 刚听完土哥的入门pytorch&#xff0c;试着写一个不完善的vgg16 VGG16具体的架构: VGG16模型构建&#xff1a; 卷积池化后尺寸计算公式&#xff1a; 引入库&#xff1a; from torch import nn from torch.nn.modules.flatten import Flattendil…

Redis解决Session共享问题

文章目录 一、集群Session共享问题二、Redis存储验证码和对象三、解决状态登录刷新问题 一、集群Session共享问题 session共享问题&#xff1a;多台Tomcat并不共享session存储空间&#xff0c;当请求切换到不同tomcat服务器时导致数据丢失的问题 tomcat可以进行多台tomcat进行…

嵌入式内核及驱动开发高级

一、起源 仅devfs&#xff0c;导致开发不方便以及一些功能难以支持&#xff1a; 热插拔 不支持一些针对所有设备的统一操作&#xff08;如电源管理&#xff09; 不能自动mknod 用户查看不了设备信息 设备信息硬编码&#xff0c;导致驱动代码通用性差&#xff0c;即没有分离…

算法与数据结构(二)--【2】链表进阶

一.循环链表 1.单循环链表/循环链表 【1】概念&#xff1a;在单链表中&#xff0c;将终端结点的指针域NULL改为指向第一个结点&#xff0c;就使整个链表形成一个环&#xff0c;这种首尾详解的链表成为循环链表。 【2】特点&#xff1a;从表中任一结点出发均可找到表中其他结点…

某网站提交登陆信息加密JS逆向实战分析

1. 写在前面 对于爬虫开发者来说&#xff0c;职业生涯中可能或多或少会遇到各种各样的网站&#xff0c;其中有些必要要求登陆才能浏览。那么模拟登陆的时候发现提交的登陆信息&#xff08;用户名、密码&#xff09;都是经过加密后的&#xff0c;如何处理&#xff1f;这里找到了…

手把手教你如何发布体验

发布工具集&#xff1a;体验中心 体验中心 (Experience Hub) 是发布流程的起点&#xff0c;也是其他工具的可扩展永久中心。从这里你们可以验证每个步骤&#xff0c;以便发布你们的体验&#xff1a; 具有当前状态的可视化任务列表 工具摘要按钮 发布/取消发布按钮 - 自动批…

【雕爷学编程】Arduino动手做(161)---16路PWM舵机驱动板2

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

【刷题】在二叉树中分配硬币

在二叉树中分配硬币 https://leetcode.cn/problems/distribute-coins-in-binary-tree/description/ 描述 给定一个有 N 个结点的二叉树的根结点 root&#xff0c;树中的每个结点上都对应有 node.val 枚硬币&#xff0c;并且总共有 N 枚硬币。 在一次移动中&#xff0c;我们…

Unity DOTS纯ECS实现虚拟摇杆Joystick控制角色移动

上篇已经实现了ECS框架下的IBeginDragHandler、IDragHandler、IEndDragHandler这几个拖动事件&#xff0c;使得可以任意给ECS框架下的UI(2D entity)响应拖动事件。本篇分享下在前篇实现的功能的基础上再实现一个常用的摇杆控制角色移动的功能。 需要注意的一点&#xff0c;目前…

如何从一个仪表盘管理多个WordPress网站?

您是否正在寻找一种管理多个WordPress网站的简单方法&#xff1f; 监控多个网站并使其保持更新可能非常耗时。 幸运的是&#xff0c;有几种 WordPress 管理工具可以让您从单个仪表板管理多个 WordPress 网站变得非常容易。这将帮助您节省大量时间&#xff0c;同时使所有 Word…

Android复杂UI的性能优化实践 - PTQBookPageView 性能优化记录

作者&#xff1a;彭泰强 1 评价指标&优化成果 要做性能优化&#xff0c;首先得知道性能怎么度量、怎么表示。因为性能是一个很抽象的词&#xff0c;我们必须把它量化、可视化。那么&#xff0c;因为是UI组件优化&#xff0c;我首先选用了GPU呈现模式分析这一工具。 在手机…