FPGA project :HDMI

news2024/11/26 15:50:04

实验目标:驱动HdMI显示十色等宽彩条。

本实验的重点是:

1掌握TMDS通信协议。

2rgb565转rgb888。

3编写HDMI驱动程序。

4学会看流程图编写代码。

值得注意的事情

1注意数据与解析数据的信号(比如传入的数据中0或者1的个数),要在时序上与数据进行对齐。

如果解析数据的信号是时序信号,那么它将会滞后数据一个clk。如果后面要用到,数据与对应的解析数据的信号同时做条件,那么需要对数据进行打一拍处理。用打拍过后的数据与解析数据的信号作为条件去做判断。

2如果一个数据是有符号位的,那么判断它的正负,就不能用简单的 > 0 来判断。

比如本实验中cnt就是5位宽的有符号数,判断其正负(cnt[4] == 1) 为负数;(cnt[4] == 0) 为正数。如果是cnt < 0 表述负数的话,那么cnt永远不会被判定为负数。

看仿真波形的经验之谈:

1在本实验与官方的编码模块代码,那么在通过功能方正,验证自己编写的编码模块代码是否正确时,可以把官方的模块例化进工程,然后仿真对比波形是否一致,即可判断自己编写的代码是否正确。

2在遇到不一致的时候,比如输入信号都一致,某个输出信号不一致。

先不要着急看去检查哪些信号会直接影响这个输出信号赋值,因为前面的一些信号,会间接影响输出信号赋值。比如影响直接影响输出信号赋值的信号。

那么此时应该先检查一些直接受输入信号影响的信号,是否正确,是否和官方给的代码波形一致;

然后再看一些”条件“波形是否正确;

也就是说由输入信号逐渐到输出信号这个过程中一次产生(你编写代码的顺序)去检查这些信号是否正确。(自顶向下)。慢慢检查。

3实在检查不出来,看看自己的代码和官方的代码编写的差在哪里。

TMDS通信协议:

一种传输视频/音频/辅助数据的传输技术:最小化传输差分信号。

采用DIV编码。附上几张图:

8bit像素信息到最小化传输直流均衡10bit数据,编码流程:

信源端与接收端的数据传输框图:由图可知,3路差分信号传输,由rgb888转10bit的数据。一路差分信号传输clock。

下面两路ddc信号是从接收端读取硬件工作模式相关信息的,本实验没有用到。(IIC通信协议。)

 模块框图:

时序图:

代码:

/*********************
    功能: 将8位rgb信号,转换成10位信号。编码
    cnt 当前时钟的值
    cnt(t - 1) 相对于当前时钟,上一个时钟周期的值
*/

module encode(
    input       wire            clk_25  ,
    input       wire            rst_n   ,
    input       wire    [7:0]   data_in ,
    input       wire            hsync   , 
    input       wire            vsync   ,
    input       wire            DE      ,

    output      wire    [9:0]   data_out 
);

    reg     [7:0]   data_in_reg1 ;
    reg     [3:0]   data_in_n1  ; // 保存传入数据1的个数.
    wire            crtl_1      ; // 一个判断条件,data_in中1的个数大于4 or 个数等于4且data_in[0] == 0
    wire    [8:0]   q_m         ;
    reg     [8:0]   q_m_reg1    ;
    reg             DE_reg1     ;
    reg             DE_reg2     ;
    reg             C0_reg1     ; // 行同步信号,打拍,为了和数据对齐。
    reg             C1_reg1     ; // 场同步信号,打拍,为了和数据对齐。
    reg             C0_reg2     ; 
    reg             C1_reg2     ; 
    reg     [9:0]   q_out       ; // 最终要输出的10为数据,经过一系列编码。
    wire            ctrl_2      ;
    wire            ctrl_3      ;
    reg     [4:0]   cnt         ; // 这是一个用于跟踪数据流差异的寄存器。正值表示已传输的“1”的超额数量。负值表示已传输的“0”的超额数量。
    reg     [3:0]   q_m_n1      ; // q_m中1的个数。cnt的最高位是符号位。有符号位的数据不能简单通过是否大于小于0来判断正负,应该判断最高位符号位的0/1(1负数,0正数)
    reg     [3:0]   q_m_n0      ; // q_m中0的个数。

/**********************************************************************************/
    // 产生第一个条件:计算输入数据中1的个数。
    always @(posedge clk_25 or negedge rst_n) begin  // 计算传入数据1的个数.
        if(~rst_n) begin
            data_in_n1 <= 4'd0 ;
        end else begin
            data_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] ;
        end
    end
    // 对输入数据打一拍,以对齐数据data_in_n1。
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            data_in_reg1 <= 8'd0 ;
        end else begin
            data_in_reg1 <= data_in ;
        end
    end
    // 根据data_in_n1与输入数据的打拍信号,描述出crtl_1判断条件。
    assign crtl_1 = ( data_in_n1 > 4 || (data_in_n1 == 4 && data_in_reg1[0] == 1'b0) ) ? 1'b1 : 1'b0 ;
    // 8bit 到 9bit 编码逻辑。
    assign q_m[0] = data_in_reg1[0] ;
    assign q_m[1] = (crtl_1) ? q_m[0]~^data_in_reg1[1] : q_m[0]^data_in_reg1[1] ;
    assign q_m[2] = (crtl_1) ? q_m[1]~^data_in_reg1[2] : q_m[1]^data_in_reg1[2] ;
    assign q_m[3] = (crtl_1) ? q_m[2]~^data_in_reg1[3] : q_m[2]^data_in_reg1[3] ;
    assign q_m[4] = (crtl_1) ? q_m[3]~^data_in_reg1[4] : q_m[3]^data_in_reg1[4] ;
    assign q_m[5] = (crtl_1) ? q_m[4]~^data_in_reg1[5] : q_m[4]^data_in_reg1[5] ;
    assign q_m[6] = (crtl_1) ? q_m[5]~^data_in_reg1[6] : q_m[5]^data_in_reg1[6] ;
    assign q_m[7] = (crtl_1) ? q_m[6]~^data_in_reg1[7] : q_m[6]^data_in_reg1[7] ;
    assign q_m[8] = (crtl_1) ? 1'b0 : 1'b1 ;
    /********************* 对q_out和cnt赋值,用到的条件 ***************************/
    // 数据q_m中1的个数和0的个数。
    always @(posedge clk_25 or negedge rst_n) begin  
        if(~rst_n) begin
            q_m_n1 <= 4'd0 ;
            q_m_n0 <= 4'd0 ;
        end else begin
            q_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 <= ~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
    end
    // 根据cnt和q_m_n1 q_m_n2 产生判断条件ctrl_2,ctrl_3。
    assign ctrl_2 = ((cnt == 5'd0) || (q_m_n1 == q_m_n0)) ? 1'b1 : 1'b0 ; // 其实可以直接写逻辑运算关系式。
    assign ctrl_3 = (((~cnt[4]) && (q_m_n1 > q_m_n0)) || ((cnt[4]) && (q_m_n1 < q_m_n0))) ? 1'b1 : 1'b0 ;
    // reg     [8:0]   q_m_reg1    ;
    // 由于q_m_n1 q_m_n0 是时序逻辑,相对于q_m就延后了一个时钟周期,为了保证qm数据与q_m_n1 q_m_n0 对齐,所以要对qm打一拍。
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            q_m_reg1 <= 8'd0 ;
        end else begin
            q_m_reg1 <= q_m ;
        end
    end
    // reg             DE_reg1     ;
    // reg             DE_reg2     ;
    // DE 逐渐的要与q_m_reg1对齐
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            DE_reg1 <= 1'b0 ;
            DE_reg2 <= 1'b0 ; 
        end else begin
            DE_reg1 <= DE      ;
            DE_reg2 <= DE_reg1 ; 
        end
    end
    // reg             C0_reg1     ; // 行同步信号,打拍,为了和数据对齐。
    // reg             C0_reg2     ; 
    // 行场同步信号,也是要与q_m_reg1对齐。
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            C0_reg1 <= 1'b0 ;
            C0_reg2 <= 1'b0 ; 
        end else begin
            C0_reg1 <= hsync   ;
            C0_reg2 <= C0_reg1 ; 
        end
    end
    // reg             C1_reg1     ; // 场同步信号,打拍,为了和数据对齐。
    // reg             C1_reg2     ;
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            C1_reg1 <= 1'b0 ;
            C1_reg2 <= 1'b0 ; 
        end else begin
            C1_reg1 <= vsync   ;
            C1_reg2 <= C1_reg1 ; 
        end
    end
    // 对q_out 与 cnt 赋值
    // q_out
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            q_out <= 10'd0 ;
            cnt   <=  5'd0 ;
        end else begin
            if(DE_reg2 == 1'b0) begin
                case ({C1_reg2 ,C0_reg2})
                2'b00: q_out[9:0] <= 10'b11010_10100 ;
                2'b01: q_out[9:0] <= 10'b00101_01011 ;
                2'b10: q_out[9:0] <= 10'b01010_10100 ;
                2'b11: q_out[9:0] <= 10'b10101_01011 ;
                default: q_out[9:0] <= 10'b11010_10100 ; // 随便挑一个。
                endcase
                cnt   <=  5'd0 ;
            end else begin
                if(ctrl_2 == 1'b1) begin
                    q_out[9] <= ~q_m_reg1[8] ; // q_out[9] <= ~q_m_reg1[8] ;
                    q_out[8] <=  q_m_reg1[8] ; // q_out[8] <=  q_m_reg1[8] ;
                    q_out[7:0] <= (q_m_reg1[8] == 1'b1) ? q_m_reg1[7:0] : ~q_m_reg1[7:0] ; // q_out[7:0] = (q_m_reg1[8] == 1'b1) ? q_m_reg1[7:0] : ~q_m_reg1[7:0] ;
                    if(q_m_reg1[8] == 1'b0) begin
                        cnt <= cnt + q_m_n0 - q_m_n1 ;
                    end else begin
                        cnt <= cnt - q_m_n0 + q_m_n1 ;
                    end
                end else begin
                    if(ctrl_3 == 1'b1) begin
                        q_out[9] <= 1'b1 ;
                        q_out[8] <= q_m_reg1[8] ;
                        q_out[7:0] <= ~q_m_reg1[7:0] ;
                        cnt <= cnt + {q_m_reg1[8], 1'b0} + q_m_n0 - q_m_n1 ; // 2 乘以 1位宽的数据,相当于把该数据左移一位。 + {q_m_reg1[8],0} + 
                    end else begin
                        q_out[9] <= 1'b0 ;
                        q_out[8] <= q_m_reg1[8] ;
                        q_out[7:0] <= q_m_reg1[7:0] ;
                        cnt <= cnt - {~q_m_reg1[8], 1'b0} - q_m_n0 + q_m_n1 ;
                    end
                end
            end
        end
    end

/************output signal descrable **************/
    assign data_out = q_out ;
endmodule
// 10位并行数据信号转换为,串行差分信号。
module par_to_ser(
    input       wire            clk_125 ,
    input       wire            rst_n   ,
    input       wire    [9:0]   data_out, // 应该在一个周期内把并行转串行?应该用到流水线技术?

    output      wire            ser_p   ,
    output      wire            ser_n   
);


/**********************************************************************************

//     // wire signal define
//     wire            dataout_flag ;
//     wire    [3:0]   datain_h_num ;
//     wire    [3:0]   datain_l_num ;
//     // reg signal define
//     reg             datain_h ;
//     reg             datain_l ;
//     reg     [3:0]   cnt_bit ;
//     reg     [9:0]   data_out_reg1 ;


// 
//     // wire            dataout_flag ;
//     assign dataout_flag = (data_out != data_out_reg1) ? 1'b1 : 1'b0 ;
//     assign datain_h_num = 2'd2*cnt_bit ;
//     assign datain_l_num = 2'd2*cnt_bit + 1'b1 ;
//     // reg             datain_h ;
//     always @(posedge clk_125 or negedge rst_n) begin
//         if(~rst_n) begin
//             datain_h <= 1'b0 ;
//         end else begin
//             datain_h <= data_out_reg1[datain_h_num] ; // 其实这里可能有一个问题,datain_h_num如果计算慢了,那么datain_h将会滞后一个clk_125.
//         end
//     end
//     // reg             datain_l ;
//     always @(posedge clk_125 or negedge rst_n) begin
//         if(~rst_n) begin
//             datain_l <= 1'b0 ;
//         end else begin
//             datain_l <= data_out_reg1[datain_l_num] ;
//         end
//     end
//     // reg     [3:0]   cnt_bit ;
//     always @(posedge clk_125 or negedge rst_n) begin
//         if(~rst_n) begin
//             cnt_bit <= 4'd0 ;
//         end else begin
//             if(dataout_flag == 1'b1 || cnt_bit == 4'd4) begin
//                 cnt_bit <= 4'd0 ;
//             end else begin
//                 cnt_bit <= cnt_bit + 1'b1 ; 
//             end
//         end
//     end
//     // reg     [9:0]   data_out_reg1 ;
//     always @(posedge clk_125 or negedge rst_n) begin
//         if(~rst_n) begin
//             data_out_reg1 <= 10'd0 ;
//         end else begin
//             data_out_reg1 <= data_out ;
//         end
//     end
************************************************************************************/

/***********************************************************************************/
// 野火教程里的方法,10bit并行数据转串行数据。
    // wire signal degine
    wire            dataout_flag ;
    wire    [4:0]   data_rise    ;
    wire    [4:0]   data_fall    ;

    // reg signal define
    reg     [3:0]   cnt_shift     ;
    reg     [9:0]   data_out_reg1 ;
    reg     [4:0]   data_rise_s   ;
    reg     [4:0]   data_fall_s   ;

    // [4:0]   data_rise  ;
    assign data_rise = {data_out[8],data_out[6],data_out[4],data_out[2],data_out[0]} ;
    // [4:0]   data_fall  ;
    assign data_fall = {data_out[9],data_out[7],data_out[5],data_out[3],data_out[1]} ;

    // wire dataout_flag;
    assign dataout_flag = (data_out != data_out_reg1) ? 1'b1 : 1'b0 ;
    // reg     [9:0]   data_out_reg1 ;
    always @(posedge clk_125 or negedge rst_n) begin
        if(~rst_n) begin
            data_out_reg1 <= 10'd0 ;
        end else begin
            data_out_reg1 <= data_out ;
        end
    end
    // reg     [3:0]   cnt_shift        ;
    always @(posedge clk_125 or negedge rst_n) begin
        if(~rst_n) begin
            cnt_shift <= 4'd0 ;
        end else begin
            if(dataout_flag == 1'b1 || cnt_shift == 4'd4) begin
                cnt_shift <= 4'd0 ;
            end else begin
                cnt_shift <= cnt_shift + 1'b1 ; 
            end
        end
    end
    // reg     [4:0]   data_rise_s   ;
    // reg     [4:0]   data_fall_s   ;
    always @(posedge clk_125 or negedge rst_n) begin
	    if(~rst_n) begin
            data_rise_s <= 5'd0 ;
            data_fall_s <= 5'd0 ;
        end else begin
            if(cnt_shift == 4'd4) begin
                data_rise_s <= data_rise ;
                data_fall_s <= data_fall ;
            end else begin
                data_rise_s <= data_rise_s[4:1] ; // 相当于右移1位。
                data_fall_s <= data_fall_s[4:1] ;
            end
        end
    end
    // 单沿到双沿采样,通过调用ddio_out实现。相当于把采样时钟翻倍。
ddio_out	ddio_out_inst0 (
	.datain_h ( data_rise_s[0] ), // 在outclk上升沿对datain_h采样传给data_out。1bit的串行数据。
	.datain_l ( data_fall_s[0] ), // 在outclk下降沿对datain_l采样传给data_out。1bit的串行数据。
	.outclock ( ~clk_125       ), // 采样时钟。

	.dataout  ( ser_p          )  
);

ddio_out	ddio_out_inst1 (
	.datain_h ( ~data_rise_s[0] ), // 单端到差分之间的转换。
	.datain_l ( ~data_fall_s[0] ), 
	.outclock ( ~clk_125        ), 

	.dataout  ( ser_n           ) 
);

endmodule

只放了两个新模块的代码。

`timescale 1ns/1ns
module test();
    reg             sys_clk     ;
    reg             sys_rst_n   ;

    wire            clk_p       ;
    wire            clk_n       ;
    wire            r_p         ;
    wire            r_n         ;
    wire            g_p         ;
    wire            g_n         ;
    wire            b_p         ;
    wire            b_n         ;
    wire            DDC_SCL     ;
    wire            DDC_SDA     ;


top top_insert(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,

    .clk_p                  ( clk_p     ) ,
    .clk_n                  ( clk_n     ) ,
    .r_p                    ( r_p       ) ,
    .r_n                    ( r_n       ) ,
    .g_p                    ( g_p       ) ,
    .g_n                    ( g_n       ) ,
    .b_p                    ( b_p       ) ,
    .b_n                    ( b_n       ) ,
    .DDC_SCL                ( DDC_SCL   ) ,
    .DDC_SDA                ( DDC_SDA   )      
);

    parameter CYCLE = 20 ;
    initial begin
        sys_clk  = 1'b1 ;
        sys_rst_n = 1'b0 ;
        #( CYCLE ) ;
        sys_rst_n = 1'b1 ;
    end
    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI视野·今日NLP 自然语言处理论文速览 第四十五期】Mon, 2 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Mon, 2 Oct 2023 Totally 44 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Efficient Streaming Language Models with Attention Sinks Authors Guangxuan Xiao, Yuandong Tian, Beidi C…

gradle中主模块/子模块渠道对应关系通过配置实现

前言&#xff1a; 我们开发过程中&#xff0c;经常会面对针对不同的渠道&#xff0c;要产生差异性代码和资源的场景。目前谷歌其实为我们提供了一套渠道包的方案&#xff0c;这里简单描述一下。 比如我主模块依赖module1和module2。如果主模块中声明了2个渠道A和B&#xff0c…

1.8.C++项目:仿muduo库实现并发服务器之eventloop模块的设计

项目完整在&#xff1a; 文章目录 一、eventloop模块&#xff1a;进行事件监控&#xff0c;以及事件处理的模块二、提供的功能三、实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#xff08;三&#xff09;功能设计 四、框架五、代码 一、eventloop模…

Andriod 简单控件

目录 一、文本显示1.1 设置文本内容1.2 设置文本大小1.3 设置文本颜色 二、视图基础2.1 设置视图宽高2.2 设置视图间距2.3 设置视图对齐方式 三、常用布局3.1 线性布局LinearLayout3.2 相对布局RelativeLayout3.3 网格布局GridLayout3.4 滚动视图ScrollView 四、按钮触控4.1 按…

Acwing 905. 区间选点

Acwing 905. 区间选点 知识点题目描述思路讲解代码展示 知识点 贪心 题目描述 思路讲解 代码展示 #include <iostream> #include <algorithm>using namespace std;const int N 1e5 10;int n;struct Range {int l, r;bool operator<(const Range &W) co…

宽带光纤接入网中影响家宽业务质量的常见原因有哪些

1 引言 虽然家宽业务质量问题约60%发生在家庭网&#xff08;见《家宽用户家庭网的主要质量问题是什么&#xff1f;原因有哪些》一文&#xff09;&#xff0c;但在用户的眼里&#xff0c;所有家宽业务质量问题都是由运营商的网络质量导致的&#xff0c;用户也因此对不同运营商家…

红外遥控器 数据格式,按下及松开判断

红外遥控是一种无线、非接触控制技术&#xff0c;具有抗干扰能力强&#xff0c;信息传输可靠&#xff0c;功耗低&#xff0c;成本低&#xff0c;易实现等显著优点&#xff0c;被诸多电子设备特别是家用电器广泛采用&#xff0c;并越来越多的应用到计算机系统中。 同类产品的红…

国庆作业5

物理层&#xff1a;负责传输比特流。它将数据转换为比特流并传输。 数据链路层&#xff1a;相邻节点的可靠传输。 网络层&#xff1a;负责在不同的网络中进行数据包的路由和转发。。 传输层&#xff1a;提供端到端的连接。 会话层&#xff1a;负责建立、管理和终止会话。它…

如何用ChatGPT学或教英文?5个使用ChatGPT的应用场景!

原文&#xff1a;百度安全验证 AI工具ChatGPT的出现大幅改变许多领域的运作方式&#xff0c;就连「学英文」也不例外&#xff01;我发现ChatGPT应用在英语的学习与教学上非常有意思。 究竟ChatGPT如何改变英文学习者(学生)与教学者(老师)呢&#xff1f; 有5个应用场景我感到…

idea清空缓存类

解决办法 网上有很多是让你去清空什么maven依赖&#xff0c;但假如这个项目是你不可以大刀阔斧的话 可以清空idea缓存 选择 Invalidate 开头的 然后全选 运行重启idea OK

免费 AI 代码生成器 Amazon CodeWhisperer 初体验

文章作者&#xff1a;浪里行舟 简介 随着 ChatGPT 的到来&#xff0c;不由让很多程序员感到恐慌。虽然我们阻止不了 AI 时代到来&#xff0c;但是我们可以跟随 AI 的脚步&#xff0c;近期我发现了一个神仙 AI 代码生产工具 CodeWhisperer &#xff0c;它是一项基于机器学习的服…

从其它环境转移到Nacos的方法-NacosSync

理解 NacosSync 组件启动 NacosSync 服务通过一个简单的例子&#xff0c;演示如何将注册到 Zookeeper 的 Dubbo 客户端迁移到 Nacos。 介绍 NacosSync是一个支持多种注册中心的同步组件,基于Spring boot开发框架,数据层采用Spring Data JPA,遵循了标准的JPA访问规范,支持多种…

【Golang】数组 切片

【Golang】数组 && 切片 1、数组 基本概念 数组是一个由固定长度的特定类型元素组成的序列&#xff0c;一个数组可以由零个或多个元素组成 因为数组的长度是固定的&#xff0c;所以在Go语言中很少直接使用数组 数组初始化 //1、默认数组中的值是类型的默认值 var arr…

buuctf-[RoarCTF 2019]Easy Java

第一次遇到java类的题目 打开环境&#xff0c;很像sql 点击help 以为是文件包含&#xff0c;&#xff0c;但是不对 这里需要了解JAVA WEB目录结构 WEB-INF&#xff1a;Java的web应用安全目录&#xff1b; 此外如果想在页面访问WEB-INF应用里面的文件&#xff0c;必须要通过w…

localStorage实现历史记录搜索功能

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;JavaScript &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; 文章目录 为什么使用localStorage如何使用localStorage实现历史记录搜索功能&#xff08…

矢量图形编辑软件illustrator 2023 mac特点介绍

illustrator 2023 mac是一款矢量图形编辑软件&#xff0c;用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator mac软件特点 矢量图形&#xff1a;illustrator创建的图形是矢量图形&#xff0c;可以无限放大而不失真&#xff0c;这与像素图形编辑软件&am…

[Linux]线程互斥

[Linux]线程互斥 文章目录 [Linux]线程互斥线程并发访问问题线程互斥控制--加锁pthread_mutex_init函数pthread_mutex_destroy函数pthread_mutex_lock函数pthread_mutex_unlock函数锁相关函数使用示例使用锁的细节加锁解锁的实现原理 线程安全概念常见的线程不安全的情况常见的…

蓝桥杯每日一题2023.10.2

时间显示 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 输入为毫秒&#xff0c;故我们可以先将毫秒转化为秒&#xff0c;由于只需要输出时分&#xff0c;我们只需要将天数去除即可&#xff0c;可以在这里多训练一次天数判断 #include<bits/stdc.h> using namespace std…

检索qpython文件夹下.py

需求口令 检索 /storage/emulated/0/qpython 文件夹下的.py文件 编号原文件名&#xff1a;复制到/storage/emulated/0/qpython/py文件/ 没有文件夹就创建 检索qpython文件夹下.py&#xff0c;复制到py文件单独路径 根据这个提问清单和步骤&#xff0c;我们需要完成以下任务&…

Audio2Face的工作原理

预加载一个3D数字人物模型(Digital Mark),该模型可以通过音频驱动进行面部动画。 用户上传音频文件作为输入。 将音频输入馈送到预训练的深度神经网络中。 Audio2Face加载预制的3d人头mesh 3D数字人物面部模型由大量顶点组成,每个顶点都有xyz坐标。 深度神经网络输入音频特征,…