前言

  • 默认在开发了视频方面后
  • 这方面的工作本来可以找技术支持拿个例程参考下,很快就可以的写出来的,以为自己对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. 第十章 nginx常用配置介绍

    一.虚拟主机 1.配置方式 #虚拟主机配置方式:1.基于多IP的方式2.基于多端口的方式3.基于多域名的方式 2.方式一:基于多IP的方式 1.第一个配置文件[root@web02 /etc/ngin ...

  2. 第六章 IP基本原理

    一.引入 1.IP是网络层协议,也是当今应用最广泛的网络协议之一 2.IP协议规定了数据的封装方式,网络节点的标识方法,用于网络上数据的端到端的传递. 二.IP协议概述 1.IP及相关协议 2.IP的 ...

  3. 简述 QPS、TPS、并发用户数、吞吐量关系

    1. QPS QPS Queries Per Second 是每秒查询率 ,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准, 即每秒的响应请求数,也即 ...

  4. 源代码 VS 汇编代码 VS 目标代码 VS 字节码 VS 机器码

    1.源代码(source code) 源代码就是平时我们开发的代码:比如C.Java.Python.Shell...等 public class HelloWorld { public static ...

  5. 【Azure云服务 Cloud Service】如何在部署云服务Cloud Service时候通过启动任务Start Task来配置IIS (如开启ARR)

    问题情形 通过VS部署Cloud Service时,需要在开始任务时候安装或配置其他任务,如安装及配置ARR. 执行步骤 1) 下载 requestRouter_amd64.msi 和 webfarm ...

  6. 【Azure 批处理 Azure Batch】在Azure Batch中如何通过开始任务自动安装第三方依赖的一些软件(Windows环境)

    准备条件 Azure Batch账号 需要安装的软件包(zip)文件,里面包含该软件的msi安装文件, 此处使用python.msi 版本 3.3.3 作为例子(https://www.python. ...

  7. Docker学习笔记之-部署.Net Core 3.1项目到Docker容器,并使用Nginx反向代理(CentOS7)(一)

    上一节演示如何安装Docker,链接:Docker学习笔记之-在CentOS中安装Docker 本节演示 将.net core 3.1 部署到docker容器当中,并使用 Nginx反向代理,部署平台 ...

  8. python提取视频第一帧图片

    一.实现代码 # -*- coding: utf-8 -*- import cv2 from PIL import Image from io import BytesIO def tryTime(m ...

  9. 初探RT-Thread系统在GD32E103x芯片上的使用,点亮LED灯

    初探RT-Thread系统在GD32E103x芯片上的使用,点亮LED灯 前言 ​ 随着中美贸易战的加剧,很多公司越来越重视使用国产技术的重要性.使用国产技术,一方面可规避国外对技术的封锁造成产品核心 ...

  10. 使用Volley获取验证码

    时间紧张,直接上代码 public class MainActivity extends AppCompatActivity { private RequestQueue queues ; Strin ...