pdm接口数字mic调试

发布时间 2023-12-19 20:01:48作者: 陈昌雄

首先,rk3566平台是带有pdm接口,因此使用数字mic不需要外挂7210这样的ic

只需要配置接口即可

    rk817-sound {
        compatible = "simple-audio-card";
        simple-audio-card,format = "i2s";
        simple-audio-card,name = "rockchip,rk817-codec";
        simple-audio-card,mclk-fs = <256>;  //chencx add

        simple-audio-card,dai-link@0 {
            format = "i2s";
            cpu {
                sound-dai = <&i2s1_8ch>;  //这是模拟功放的
            };
            codec {
                sound-dai = <&rk817_codec 0>;  //这是codec节点
            };
        };

        simple-audio-card,dai-link@1 {
            format = "pdm";
            cpu {
                sound-dai = <&pdm>;  //这是数字pdm节点,需要自己配置
            };
            codec {
                sound-dai = <&rk817_codec 1>;   //把数字Pdm加入到codec声卡中
            };
        };


    };

  接着就是配置pdm参数而已,这个可以参考doc下面文档,我也是参照配置来的

//chencx add pdm
&pdm {
    status = "okay";
    #sound-dai-cells = <0>;
    pinctrl-names = "default";
    rockchip,path-map = <1 0 2 3>;  //修改默认通道顺序
    capture,channel-mapping = <2>;
    pinctrl-0 = <
            &pdmm0_clk1
            &pdmm0_sdi1 //接的sdi1接口,这个按照原理图来
            >;
};

 文档在 Y:\rk\rk3566\rk3566\RKDocs\common\Audio\Rockchip_Developer_Guide_Audio_CN.pdf

 然后需要在codec下面增加pdmdata-out-enable的属性

        rk817_codec: codec {
            #sound-dai-cells = <1>;
            compatible = "rockchip,rk817-codec";
            clocks = <&cru I2S1_MCLKOUT_TX>;
            clock-names = "mclk";
            //assigned-clocks = <&cru I2S1_MCLKOUT_TX>;
            //assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>;

            assigned-clocks = <&cru I2S1_MCLKOUT>, <&cru I2S1_MCLK_TX_IOE>;
            assigned-clock-rates = <12288000>;
            //assigned-clock-rates = <11289600>;
            assigned-clock-parents = <&cru I2S1_MCLKOUT_TX>, <&cru I2S1_MCLKOUT_TX>;

            pinctrl-names = "default";
            pinctrl-0 = <&i2s1m0_mclk>;
            hp-volume = <3>;
            spk-volume = <3>;//max-0  min-255
            out-l2spk-r2hp;
            //数字pdm
            pdmdata-out-enable;
            //喇叭控制脚
            spk-ctl-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
            mic-ctl-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
            status = "okay";
        };
    };
};

 

查看生成的节点

 ls /dev/snd/* -ls

crw-rw---- 1 system audio 116, 5 2021-12-04 06:44 controlC0
crwxrwxrwx 1 system audio 116, 2 2021-12-04 06:44 pcmC0D0c
crw-rw---- 1 system audio 116, 4 2021-12-04 06:44 pcmC0D1c //增加的输入节点
crw-rw---- 1 system audio 116, 3 2021-12-04 06:44 pcmC0D1p
crw-rw---- 1 system audio 116, 33 2021-12-04 06:44 timer

  

调试中遇到的问题

 
使用tinuycap的时候 -D 是声卡 -d是devices,所以这里使用命令-d为1
 
tinycap 32bit-44k.wav -D 0 -d 1 -c 2 -r 16000 -b 32 -p 1024 -n 3 -T 20

 

 
使用后发现还是没有声音,命令改为-c 8才有,因为默认通道0 1 上面采集数据,这里是多通道配置,所以没有声音,-c 8后面就看到声音很小,实际上是有声音的而且正常
 
之后修改声卡声音顺序,把通道顺序调整,就可以在默认声卡使用了
rockchip,path-map = <1 0 2 3>; //先采集1 通道 然后 0 2 3 。这样就把有声音的通道1作为 优先采集了
 
 
 
经过这次操作 就可以录制到正常的声卡声音,但是声音比较小
 
之后,使用拾音算法,就可增加声音增益了,
 
修改 external/tinyalsa//pcm.c
 
static short out_vol = 5.0;
static void volume_process(const void *buffer, unsigned int channels,size_t length, short volume) {

short * buffer_end = (short*)buffer + length/2;
short * pcmData = (short *)buffer;
int i = 0;
int pcmval;
int tenp = channels ;
       while (pcmData < buffer_end) {
      /// if (i % channels != 1 && i % channels != 0) {
      /// printf("***\n");
               pcmval = (short)*pcmData * volume;
                if (pcmval < 32768 && pcmval > -32768) {
                        *pcmData = pcmval;
                } else if (pcmval > 32767) {
                        *pcmData = 32767;
                } else if (pcmval < -32767) {
                        *pcmData = -32767;
                }
      ///}
            ++pcmData;
        i++;
       }
}
.........
int pcm_read(struct pcm *pcm, void *data, unsigned int count)
{
    struct snd_xferi x;
int i = 0 ;
short *temp = (short*)data ;
    if (!(pcm->flags & PCM_IN))
        return -EINVAL;
//printf("start---read---\n") ;
   memset(data, 0, count);
    x.buf = data;
    x.frames = count / (pcm->config.channels *
                        pcm_format_to_bits(pcm->config.format) / 8);

    for (;;) {
        if (!pcm->running) {
            if (pcm_start(pcm) < 0) {
                fprintf(stderr, "start error");
                return -errno;
            }
        }
..................................................
for(i=0;i<10;i++)
{
    printf("%d\n", temp[i]) ;
}

//printf("---\n");
 volume_process(x.buf, pcm->config.channels,count , out_vol);
        return 0;
    }
}

 

到这里,使用是没有什么问题了