HDMI20协议解析_Audio_Sample

HDMI20协议解析_Audio_Sample


1.版本说明

日期作者版本说明
202409XX风释雪初始版本

2.概述

当通过HDMI传输音频信号时,Audio_Sample是必须要传输的数据包之一;
通过前端硬件或软件收到PCM原始音频数据后,需要通过Audio_Sample packet发送给sink端,
sink端收到后,结合协议解析出原始PCM音频数据,用来播放声音;
同时(重点),该协议还会按照IEC-60958打包传输通道状态信息,该信息包含音频采样位宽,
音频采样率,通道数量等信息,非常重要!!


3.目标

FPGA 实现 HDMI2.0 TX/RX功能,生成或解析对应的Audio Sample数据包,用于传输双通道立体声


4.协议解析

  • 协议分类

  • 在这里插入图片描述

  • 协议格式

  • 在这里插入图片描述


5.参数分析

  • layout

  • 在这里插入图片描述

  • 通常 HDMI只传输2个通道,因此 layout = 0;

  • sample_present.sp[3:0] : 有效通道使能bit,当传输2个通道时,4’b0001

  • sample_flat.sp[3:0] : 固定 4’b0000

  • 在这里插入图片描述

  • B[3:0] : 音频帧起始状态,根据IEC-60958, 每一帧包含192个subframe,计数器0-191, 当等于0时,B[x] = 1

B.X [4 fields, 1 bit each] B.X =1 if Subpacket X contains the first frame in a 192
frame IEC 60958 Channel Status block; B.X = 0 otherwise
备注:需要先理解 IEC-60958
  • L/R 左右声道数据
  • P/C/U/V
    P : 校验
    U : 用户数据,固定 0
    V : 固定 0
    C : 状态信息bit,参考IEC-60958,该信息包含音频采样位宽,音频采样率,通道数量等信息,非常重要!!

6.IEC-60958

  • 参考 https://blog.csdn.net/luckywang1103/article/details/88886810 (感谢分享)

  • 参考 https://www.cnblogs.com/fellow1988/p/6445489.html (感谢分享)

  • 在这里插入图片描述

  • 在这里插入图片描述

  • 总结 :

    一个block,共 192 Frames, 一个Frames等于2个(左+右)subframe,每个subframe代表一个声道的音频数据+V/U/C/P+其他数据(不关心)
    因此, 一个block,可以传输 192个左右声道数据,加192bit左右通道信息数据

7.C 通道信息

  • 每个声道的通道信息共 192 bit, 每个audio sample packet 只传输1个bit,共需要192次才能传输完;
  • C 通道信息包含 消费级 和 专业级, 日常使用为消费级;
  • 在这里插入图片描述
status[0] : PRO = 1'b0 消费级
status[1] : AUDIO = 1'b0
status[2] : Copy = 1'b0
status[5:3] : Emphasis = 3'b000
status[7:6] : Mode = 2'b00
status[15:8] : Category Code = 8'b10000000
status[19:16] : Source Num = 4'b0000
status[23:20] : Channel Num = 4'b0001 (Left) 4'b0010 (Right)
status[27:24] : FS = 4'b0000(44.1K) 4'b1000(88.2K) 4'b1100(176.4K) 4'b0010 (48K) 4'b1010 (96K) 4'b1110 (192K)
status[29:28] : Clock Acc = 2'b00
status[32] : Word Max = 1'b0  Max word length is 20 bits , Word Max = 1'b1  Max word length is 24 bits,
status[35:33] :  Word Length = IF(Word Max == 1'b0) : 3'b001(16bits), 3'b010(18bits) 3'b100(19bits) 3'b101(20bits) 3'b110(17bits)
-----------------Word Length = IF(Word Max == 1'b1) : 3'b001(20bits), 3'b010(22bits) 3'b100(23bits) 3'b101(24bits) 3'b110(21bits)

8.P 校验

    P = ^ {C, U, V, DATA[23:0]}

9.软件实现

// ch1
wire           [24                      -1 : 0] ch1_data                    ;
wire                                            ch1_c                       ; // 0 not use 1 use
wire                                            ch1_u                       ; // 0 not use 1 use
wire                                            ch1_v                       ; // 0 valid 1 no valid
wire                                            ch1_p                       ;
// ch2
wire           [24                      -1 : 0] ch2_data                    ;
wire                                            ch2_c                       ; // 0 not use 1 use
wire                                            ch2_u                       ; // 0 not use 1 use
wire                                            ch2_v                       ; // 0 valid 1 no valid
wire                                            ch2_p                       ;

reg            [192                    - 1 : 0] status_l                    = 0;
reg            [192                    - 1 : 0] status_r                    = 0;

reg            [8                      - 1 : 0] cnt                         = 0;

always @(posedge clk) begin
    status_l[0]      <= 1'b0;
    status_l[1]      <= 1'b0;
    status_l[2]      <= 1'b0;
    status_l[5:3]    <= 3'b000;
    status_l[7:6]    <= 2'b00;
    status_l[15:8]   <= 8'b10000000;
    status_l[19:16]  <= 4'b0000;
    status_l[23:20]  <= 4'b0001;
    status_l[27:24]  <= (aud_fs == `ARG_AUD_44_1KFS) ? 4'b0000 : (aud_fs == `ARG_AUD_48KFS) ? 4'b0010 : 4'b0010 /* (48K) */;
    status_l[29:28]  <= 2'b00;
    status_l[31:30]  <= 2'b00;
    status_l[32]     <= 1'd1;
    status_l[35:33]  <= (aud_bit == `ARG_AUD_16BIT) ? 3'b001 : (aud_bit == `ARG_AUD_24BIT) ? 3'b101 : 3'b101 /* (24bits) */;
    status_l[191:36] <= 156'd0;

    status_r[0]      <= 1'b0;
    status_r[1]      <= 1'b0;
    status_r[2]      <= 1'b0;
    status_r[5:3]    <= 3'b000;
    status_r[7:6]    <= 2'b00;
    status_r[15:8]   <= 8'b10000000;
    status_r[19:16]  <= 4'b0000;
    status_r[23:20]  <= 4'b0010;
    status_r[27:24]  <= (aud_fs == `ARG_AUD_44_1KFS) ? 4'b0000 : (aud_fs == `ARG_AUD_48KFS) ? 4'b0010 : 4'b0010 /* (48K) */;
    status_r[29:28]  <= 2'b00;
    status_r[31:30]  <= 2'b00;
    status_r[32]     <= 1'd1;
    status_r[35:33]  <= (aud_bit == `ARG_AUD_16BIT) ? 3'b001 : (aud_bit == `ARG_AUD_24BIT) ? 3'b101 : 3'b101 /* (24bits) */;
    status_r[191:36] <= 156'd0;
end

assign {ch2_data, ch1_data} = aud_data;

assign ch1_c = status_l[cnt];
assign ch1_u = 1'd0;
assign ch1_v = 1'd0;
assign ch1_p = (^ch1_data[23:0]) ^ ch1_c ^ ch1_u ^ ch1_v;

assign ch2_c = status_r[cnt];
assign ch2_u = 1'd0;
assign ch2_v = 1'd0;
assign ch2_p = (^ch2_data[23:0]) ^ ch2_c ^ ch2_u ^ ch2_v;


5.参考文档

  • EIA-CEA-861-D
  • HDMI 1.4(1.4b/2.0)
  • IEC-60958-1
  • IEC-60958-3-2003

在这里插入图片描述


在这里插入图片描述

td_s32 sample_audio_ai_hdmi_ao(td_void) { td_s32 ret; td_u32 ai_chn_cnt; td_u32 ao_chn_cnt; ot_audio_dev ai_dev; ot_audio_dev ao_dev = SAMPLE_AUDIO_INNER_HDMI_AO_DEV; ot_aio_attr aio_attr = {0}; ot_aio_attr hdmi_ao_attr = {0}; sample_comm_ai_vqe_param ai_vqe_param = {0}; sample_audio_ai_hdmi_ao_init_param(&aio_attr, &ai_dev, &hdmi_ao_attr); /* enable AI channel */ ai_chn_cnt = aio_attr.chn_cnt; aio_attr.work_mode = OT_AIO_MODE_I2S_MASTER; sample_audio_set_ai_vqe_param(&ai_vqe_param, OT_AUDIO_SAMPLE_RATE_BUTT, TD_FALSE, TD_NULL, 0); ret = sample_comm_audio_start_ai(ai_dev, ai_chn_cnt, &aio_attr, &ai_vqe_param, -1); if (ret != TD_SUCCESS) { sample_dbg(ret); goto hdmi_err2; } /* enable AO channel */ ao_chn_cnt = hdmi_ao_attr.chn_cnt; ret = sample_comm_audio_start_ao(ao_dev, ao_chn_cnt, &hdmi_ao_attr, g_in_sample_rate, g_aio_resample); if (ret != TD_SUCCESS) { sample_dbg(ret); goto hdmi_err1; } /* config audio codec */ ret =sample_es8388_cfg_audio(aio_attr.work_mode, aio_attr.sample_rate, aio_attr.chn_cnt); if (ret != TD_SUCCESS) { sample_dbg(ret); goto hdmi_err0; } /* AI to AO channel */ ret = sample_audio_ao_bind_ai_multi_chn(ai_dev, ai_chn_cnt, ao_dev); if (ret != TD_SUCCESS) { goto hdmi_err0; } printf("\nplease press twice ENTER to exit this sample\n"); smaple_audio_getchar(); smaple_audio_getchar(); sample_audio_ao_unbind_ai_multi_chn(ai_dev, ai_chn_cnt); hdmi_err0: ret = sample_comm_audio_stop_ao(ao_dev, hdmi_ao_attr.chn_cnt, TD_FALSE); if (ret != TD_SUCCESS) { sample_dbg(ret); } hdmi_err1: ret = sample_comm_audio_stop_ai(ai_dev, ai_chn_cnt, TD_FALSE, TD_FALSE); if (ret != TD_SUCCESS) { sample_dbg(ret); } hdmi_err2: return ret;详细解析
06-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值