前言

  • 默认在开发了视频方面后
  • 这方面的工作本来可以找技术支持拿个例程参考下,很快就可以的写出来的,以为自己对HDMI协议不太了解,但是技术支持说没有,所以没办法,只能自己搞了
  • 看手册不难,难得找是资料
  • 记录一下,也分享一下

参考

  • sil9136寄存器手册:《Sil-PR-1060-C》
  • HDMI协议手册:《HDMI_1.4》
  • CEA标准手册:《CEA-861-D[安全]》
  • 使用参考例程无音频功能

手册使用+实战

  • 以 I2S 接口为例开发
  • 直接看手册配置相关寄存器
  • 记得输入与输出配对
    • 如编码类型
    • 采样长度
    • 采样频率
    • 等等

配置

  • 《Sil-PR-1060-C》手册,28页起

  • 图中说明 sil9136 支持 S/PDIF, I2S or DSD模式,主机可以通过配置TPI选择不同的模式

  • 这个寄存器表比较重要,说明了sil9136的寄存器配置

  • 0x26 寄存器

    • [7:6]

      • 选择模式,支持

        • none
        • S/PDIF
        • I2S
        • DSD
    • [5]
      • 通道数,支持

        • 双通道
        • 8 通道
    • [4]
      • 静音配置
    • [3:0]
      • 编码类型,有

        • Refer to Stream Header
        • PCM (本次使用 PCM)
        • AC-3
        • MPEG1
        • MP3
        • MPEG2
        • AAC
        • DTS
        • ATRAC
  • 0x27 寄存器

    • [7:6]

      • 音频采样比特位长度 SS

        • Refer to Stream Header
        • 16 bit
        • 20 bit
        • 24 bit
    • [5:3]
      • 音频采样频率 SF

        • Refer to Stream Header
        • 32 kHz
        • 44.1 kHz
        • 48 kHz
        • 88.2 kHz
        • 96 kHz
        • 176.4 kHz
        • 192 kHz
    • [2]
      • 是否支持高比特率
  • 注意:图中说明的 0x24 和 0x25 寄存器只有在 S/PDIF 模式下有效,即是 0x26[7:6]=01 时。

Configuring Audio Using I2S

  • 直接跳到配置 I2S 流程,实现配置逻辑

    • 上图已经很明显地显示出了配置出 I2S 的流程了
    • 步骤:
      1. 确保有有效的 I2S 信号进入 sil9136
      2. 设置 0x26[4] 为静音模式
        • 直接调用例程接口:SetAudioMute(AUDIO_MUTE_MUTED);
      3. 通过 0x20 来配置进来的 SD 格式
          • 配置要和输入的音频配置搭配
          • 以下为个人选择
            • SCK Sample Edge :Rising
            • MCLK Multiplier:256
            • WS Polarity – Left when:WS is Low
            • SD Justify Data is justified:Left
            • SD Direction Byte shifted first:MSB
            • WS to SD First Bit Shift:Yes
          • 程序为:WriteByteTPI(TPI_I2S_IN_CFG, (0x80x10));
      4. 通过多次设置 0x1F 来配置每一个 SD 输入映射
          • SDx与FIFOn的映射
          • 支持一对多
          • 注意:必须顺序映射,如如果要映射FIFO2,就必须先完成FIFO0和FIFO1的映射
          • 我的代码段:SD0-FIFO0; SD1-FIFO1; SD2-FIFO2; SD3-FIFO3;
            do{
            WriteByteTPI(TPI_I2S_EN, 0x80);
            Tmp = ReadByteTPI(TPI_I2S_EN);
            }while(Tmp != 0x80);
            do{
            WriteByteTPI(TPI_I2S_EN, 0x91);
            Tmp = ReadByteTPI(TPI_I2S_EN);
            }while(Tmp != 0x91);
            do{
            WriteByteTPI(TPI_I2S_EN, 0xA2);
            Tmp = ReadByteTPI(TPI_I2S_EN);
            }while(Tmp != 0xA2);
            do{
            WriteByteTPI(TPI_I2S_EN, 0xB3);
            Tmp = ReadByteTPI(TPI_I2S_EN);
            }while(Tmp != 0xB3);
      5. 通过设置 0x27[5:3] 来配置音频采样频率
        • 配置为48kHz:ReadModifyWriteTPI(TPI_AUDIO_SAMPLE_CTRL, 0x38, 0x18);
      6. 设置 0x21-0x25 来配置发送到HDMI的头信息
          • 上图 0x21-0x25 的描述在 I2S 模式有效,即是 0x26[7:6] = 0x10
          • 主要配置两个参数
            1. 采样频率:48 kHz
            2. 采样长度:24 bits
          • 代码段
                WriteByteTPI(TPI_I2S_CHST_0, 0x00);
            WriteByteTPI(TPI_I2S_CHST_1, 0x00);
            WriteByteTPI(TPI_I2S_CHST_2, 0x00);
            WriteByteTPI(TPI_I2S_CHST_3, 0x02);
            WriteByteTPI(TPI_I2S_CHST_4, 0x0B);
      7. 设置 0xBF-0xCD 来配置 audio infoframe
        • 这步骤先给出最终代码再分析:SetAudioInfoFrames(TWO_CHANNELS, 0x00, 0x00, 0x18, 0x00);

          • 说明了配置 audio infoframe 的必要性和需要参考的文件 HDMI Specification,根据本文件说明,了解到sil9136 支持 HDMI1.4 协议,所以准备好文件《HDMI_1.4》,并找到关于 audio infoframe 的说明。

          • 图A

          • 图B

          • 图C

            • 图Cc1,《CEA-861-D安全》

            • 图Cc2,《CEA-861-D安全》

          • 图D

          • 结合例程源码 bool SetAudioInfoFrames 函数,得出只需要了解几个参数配置即可。

            • byte ChannelCount

              • 参照图C和图Cc1,C0...C2,选择双通道,得出值为 0x01
            • byte CodingType
              • CT0...CT3: The CT bits shall always be set to a value of 0 (“Refer to Stream Header”).即是置为0即可
            • SS
              • The SS bits shall always be set to a value of 0 (“Refer to Stream Header”). 即是置为0即可
            • Fs
              • 参考源码、0x27寄存器、图C和图Cc2
              • 推测 Fs 就是采样频率 SF0...SF2
              • B_Data[6] = (Fs >> 1) | (SS >> 6);
                • Fs在图C中的PB2[4:2],而上述代码中右移一位,所以 Fs 的值占用[5:3],参考0x27。
                • 采样频率为 48kHz,得出 Fs=x018
            • SpeakerConfig
              • 参考源码 B_Data[8] = SpeakerConfig; 得出 SpeakerConfig 为 图C中的PB4
              • 这里为 LPCM ,所以 SpeakerConfig = 0;
            //////////////////////////////////////////////////////////////////////////////
            //
            // FUNCTION : SetAudioInfoFrames()
            //
            // PURPOSE : Load Audio InfoFrame data into registers and send to sink
            //
            // INPUT PARAMS : (1) Channel count (2) speaker configuration per CEA-861D
            // Tables 19, 20 (3) Coding type: 0x09 for DSD Audio. 0 (refer
            // to stream header) for all the rest (4) Sample Frequency. Non
            // zero for HBR only (5) Audio Sample Length. Non zero for HBR
            // only.
            //
            // OUTPUT PARAMS : None
            //
            // GLOBALS USED : None
            //
            // RETURNS : TRUE
            //
            //////////////////////////////////////////////////////////////////////////////
            bool SetAudioInfoFrames(byte ChannelCount, byte CodingType, byte SS, byte Fs, byte SpeakerConfig)
            {
            byte B_Data[SIZE_AUDIO_INFOFRAME]; // 14
            byte i;
            TPI_TRACE_PRINT((">>SetAudioInfoFrames()\n"));
            for (i = 0; i < SIZE_AUDIO_INFOFRAME +1; i++)
            B_Data[i] = 0;
            B_Data[0] = EN_AUDIO_INFOFRAMES; // 0xC2
            B_Data[1] = TYPE_AUDIO_INFOFRAMES; // 0x84
            B_Data[2] = AUDIO_INFOFRAMES_VERSION; // 0x01
            B_Data[3] = AUDIO_INFOFRAMES_LENGTH; // 0x0A
            B_Data[5] = ChannelCount; // 0 for "Refer to Stream Header" or for 2 Channels. 0x07 for 8 Channels
            B_Data[5] |= (CodingType << 4); // 0xC7[7:4] == 0b1001 for DSD Audio
            B_Data[4] = 0x84 + 0x01 + 0x0A; // Calculate checksum
            // B_Data[6] = (Fs << 2) | SS;
            B_Data[6] = (Fs >> 1) | (SS >> 6);
            //write Fs to 0x27[5:3] and SS to 0x27[7:6] to update the IForm with the current value.
            // ReadModifyWriteTPI(TPI_AUDIO_SAMPLE_CTRL, BITS_7_6 | BITS_5_4_3, (B_Data[6] & BITS_1_0) << 6 | (B_Data[6] & 0x1C) << 1);
            B_Data[8] = SpeakerConfig;
            for (i = 5; i < SIZE_AUDIO_INFOFRAME; i++)
            B_Data[4] += B_Data[i];
            B_Data[4] = 0x100 - B_Data[4];
            g_audio_Checksum = B_Data[4]; // Audio checksum for global use
            WriteBlockTPI(TPI_AUDIO_BYTE_0, SIZE_AUDIO_INFOFRAME, B_Data);
            #ifdef DEV_EMBEDDED
            EnableEmbeddedSync();
            #endif
            return TRUE;
            }
      8. I2S 模式, 设置音频通道数,并关闭静音
        1. 代码:WriteByteTPI(TPI_AUDIO_INTERFACE_REG, AUD_IF_I2S | TWO_CHANNEL_LAYOUT | 0x01);
        2. 注意:audio inframe中的通道数配置必须和 0x26 配置的一样

总结实现

  • 得出一下代码,并把一下函数放到热插拔的插入后运行即可
/**
* @brief setPrivateAudio(void)
* @param
* @retval
* @author lzm
*/
void setPrivateAudio(void)
{
byte Tmp = 0; /* Select I2S input mode using TPI 0x26[7:6], with Mute enabled (bit [4] = 1). */
SetAudioMute(AUDIO_MUTE_MUTED); /* Write register TPI 0x20 to select the general incoming SD format. */
WriteByteTPI(TPI_I2S_IN_CFG, (SCK_SAMPLE_EDGE | 0x10)); /* Write register TPI 0x1F up to four times, to program each of the SD inputs. */
do{
WriteByteTPI(TPI_I2S_EN, 0x80);
Tmp = ReadByteTPI(TPI_I2S_EN);
}while(Tmp != 0x80);
do{
WriteByteTPI(TPI_I2S_EN, 0x91);
Tmp = ReadByteTPI(TPI_I2S_EN);
}while(Tmp != 0x91);
do{
WriteByteTPI(TPI_I2S_EN, 0xA2);
Tmp = ReadByteTPI(TPI_I2S_EN);
}while(Tmp != 0xA2);
do{
WriteByteTPI(TPI_I2S_EN, 0xB3);
Tmp = ReadByteTPI(TPI_I2S_EN);
}while(Tmp != 0xB3); // /* Program register TPI 0x27 with the correct audio about. */
// WriteByteTPI(TPI_AUDIO_SAMPLE_CTRL, AUDIO_SAMPLE_SIZE_24BIT | AUDIO_SAMPLE_FREQ_48KHZ | AUDIO_SAMPLE_HBR_DISABLE);
/* Program register TPI 0x27[5:3] with the correct audio rate */
ReadModifyWriteTPI(TPI_AUDIO_SAMPLE_CTRL, 0x38, AUDIO_SAMPLE_FREQ_48KHZ); /* Program registers TPI 0x21-x25 with the correct header information for the stream that will be sent over HDMI. */
WriteByteTPI(TPI_I2S_CHST_0, 0x00);
WriteByteTPI(TPI_I2S_CHST_1, 0x00);
WriteByteTPI(TPI_I2S_CHST_2, 0x00);
WriteByteTPI(TPI_I2S_CHST_3, 0x02);
WriteByteTPI(TPI_I2S_CHST_4, 0x0B); /* Write registers TPI 0xBF-xCD with the appropriate Audio InfoFrame information. */
SetAudioInfoFrames(TWO_CHANNELS, 0x00, 0x00, 0x18, 0x00);
/* Set the audio packet header layout indicator to 2-channel or multi-channel mode as needed using the sequence described below.
Note that Audio InfoFrame byte 1 must also have this same setting. */ /* Again write register TPI 0x26 with I2S selected, this time with Mute disabled (bit [4] = 0). */
WriteByteTPI(TPI_AUDIO_INTERFACE_REG, AUD_IF_I2S | TWO_CHANNEL_LAYOUT | 0x01);
SetAudioMute(AUDIO_MUTE_NORMAL);
}

【芯片手册开发】Sil9136音频开发详细分析+源码实战的更多相关文章

  1. 【linux】i2c使用分析&源码实战

    目录 前言 1. 设备检查命令 1.1 查看I2C驱动 1.2 i2c-tools 1.2.1 I2C-detect安装 1.2.2 i2cdetect 命令 1.2.3 i2cget 命令 1.2. ...

  2. 【linux】系统调用版串口分析&源码实战

    目录 前言 参考 1. 实战分析 1.1 开发步骤 1.1.1 获取串口设备路径 1.1.2 打开设备文件 1.1.3 配置串口 termios 结构体 1. c_iflag 输入模式标志 2. c_ ...

  3. springboot+mybatis+bootstrap开发员工oa后台管理系统项目源码

    java项目源码详情描述:S020<springboot+mybatis+bootstrap开发员工oa后台管理系统项目源码>jboa项目有请假以及报销单的申请和审核session共享加登 ...

  4. 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 百篇博客分析OpenHarmony源码 | v13.02

    百篇博客系列篇.本篇为: v13.xx 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 51.c.h .o 几点说明 kernel_liteos_a_note | 中文注解鸿蒙内核 ...

  5. Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例

    概要  前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类——LinkedList.和学习ArrayList一样,接下来呢,我们先对Linked ...

  6. Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例

    概要 这一章,我们对HashMap进行学习.我们先对HashMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashMap.内容包括:第1部分 HashMap介绍第2部分 HashMa ...

  7. Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例

    概要 前一章,我们学习了HashMap.这一章,我们对Hashtable进行学习.我们先对Hashtable有个整体认识,然后再学习它的源码,最后再通过实例来学会使用Hashtable.第1部分 Ha ...

  8. Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  9. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

随机推荐

  1. Windows Server 设置自动登陆

    前言 Windows Server 相信很多人都在使用,但是系统每次登陆都比较麻烦,能否设置自动登陆呢?有兴趣一起来学习一下吧!的自动登陆方法也比较多,在此分享一个实用简单的,通过命令来设置" ...

  2. docker19.03限制容器使用的内存资源

    一,指定内存大小的参数: [root@localhost liuhongdi]# docker run -idt --name kafka2 --hostname kafka2 -m 200M --m ...

  3. 面试官:为什么MySQL的索引要使用B+树,而不是其它树?比如B树?

    InnoDB的一棵B+树可以存放多少行数据? 答案:约2千万 为什么是这么多? 因为这是可以算出来的,要搞清楚这个问题,先从InnoDB索引数据结构.数据组织方式说起. 计算机在存储数据的时候,有最小 ...

  4. 【应用程序见解 Application Insights】使用Azure Monitor Application Insights Agent获取Azure VM中监控数据及IIS请求指标等信息

    问题情形 为了使用Application Insights也可以监控Azure VM中的相关性能数据,如CPU, Memory,IIS Reuqest等信息,可以在VM中开始一个一个扩展插件: Azu ...

  5. Spring Aop 详解二

    这是Spring Aop的第二篇,案例代码很详解,可以查看https://gitee.com/haimama/java-study/tree/master/spring-aop-demo. 阅读前,建 ...

  6. Asp.Net Core如何根据数据库自动生成实体类

    通过引用Nuget包添加实体类 运行 Install-Package Microsoft.EntityFrameworkCore.SqlServer 运行 Install-Package Micros ...

  7. 一文秒懂!Python字符串格式化之format方法详解

    format是字符串内嵌的一个方法,用于格式化字符串.以大括号{}来标明被替换的字符串,一定程度上与%目的一致.但在某些方面更加的方便 1.基本用法 1.按照{}的顺序依次匹配括号中的值 s = &q ...

  8. find for /f 分割字符串 bat

    @Echo off::总用例数For /f "tokens=2" %%i in ('Type bat.txt^|Find "Ran"') do (Echo %% ...

  9. leetcode学习总结

    转自https://leetcode-cn.com/ 1.两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以 ...

  10. Redis集群环境搭建实践

    0 Redis集群简介 Redis集群(Redis Cluster)是Redis提供的分布式数据库方案,通过分片(sharding)来进行数据共享,并提供复制和故障转移功能.相比于主从复制.哨兵模式, ...