StartKITでI2S Communication, Rpi Audio Board (TI/PCM5102A)を鳴らす

( XMOS startKIT, Raspberry PI Audio Board Connection )

( XMOS I2S Slave Audio )

XMOS StartKITには、Raspberry PI Extension Boardとピンコンパチブルな端子があります。

ここにRaspberry Piのオーディオボードを接続します。

上記StarKITレイアウトのDがRaspberry PIコンパチブルな端子です。今回はここにピンヘッダを搭載し、オーディオボードと接続します。

(ただ、実際に使用するのは、電源、グランドラインのみだけです。TI社のPCM5102Aは電源オンでDACとして動作し始めます)

I2S(BCLK,LRCK,DIN)はCコネクタのいくつかの1ビットポートとRaspberry PI Audio Board P5コネクタのBCLK/LRCK/DINと接続します。

Raspberry PI P5コネクタ:

Raspberry PI P5コネクタは上記のようになっています。ここで、今回使用するのは#3/BCLK, #4/LRCK, #5/DINです。

DACが正しく動作するかの確認:

接続が完了したら、DACから音が出力されるかを確認します。

上記、J7の#2,#3,#4にそれぞれ、BCLK, LRCK, DINを入力します。それをXMOSより出力し、J7の#1,#10,#11から出力します。

このJ7の#1,#10,#11をRaspberry PI P5の#3, #4,#5に接続してオーディオ出力を確認します。

実際の接続状況

コード1(パススルー):

port J7_1 = XS1_PORT_1F; // J7#1 port BCLK_IN = XS1_PORT_1H; // J7#2 port LRCK_IN = XS1_PORT_1G; // J7#3 port ADIN_IN = XS1_PORT_1E; // J7#4 port J7_10 = XS1_PORT_1J; port J7_11 = XS1_PORT_1K; clock clk1 = XS1_CLKBLK_1; clock clk2 = XS1_CLKBLK_2; clock clk3 = XS1_CLKBLK_3; void port_test(void) { printf("port_test() started.\n"); configure_clock_src(clk1, BCLK_IN); configure_port_clock_output(J7_1, clk1); configure_clock_src(clk2, LRCK_IN); configure_port_clock_output(J7_10, clk2); configure_clock_src(clk3, ADIN_IN); configure_port_clock_output(J7_11, clk3); start_clock(clk1); start_clock(clk2); start_clock(clk3); }

コード2(ストリームチャネルを使用してループバック):

#include <stdio.h>

#include <platform.h>

#include <xs1.h>

#include <xclib.h>

#include <timer.h>

port J7_1 = XS1_PORT_1F; // J7#1 -> BCLK out

port BCLK_IN = XS1_PORT_1H; // J7#2

port LRCK_IN = XS1_PORT_1G; // J7#3

in buffered port:32 ADIN_IN = XS1_PORT_1E; // J7#4

out buffered port:32 ADOUT_OUT = XS1_PORT_1K; // J7#11

port J7_10 = XS1_PORT_1J; // LRCK out

clock clk1 = XS1_CLKBLK_1;

clock clk2 = XS1_CLKBLK_2;

void set_audio_thru( streaming chanend cin,streaming chanend cout)

{

int lr = 0;

unsigned frame_counter = 0;

unsigned int x;

int t;

printf("set_audio_thru() started.\n");

set_clock_src(clk1, BCLK_IN);

set_port_clock(LRCK_IN, clk1);

set_port_clock(ADIN_IN, clk1);

set_port_clock(ADOUT_OUT, clk1);

configure_port_clock_output(J7_1, clk1);

configure_clock_src(clk2, LRCK_IN);

configure_port_clock_output(J7_10, clk2);

start_clock(clk1);

start_clock(clk2);

while (1) {

LRCK_IN when pinsneq(lr) :> lr @ t;

asm("setpt res[%0], %1" :: "r"(ADIN_IN), "r"(t + 24));

cout :> x;

partout_timed(ADOUT_OUT,24,bitrev(x),(t + 33));

asm("in %0, res[%1]" : "=r"(x) : "r"(ADIN_IN));

x = bitrev(x) << 8;

cin <: x;

frame_counter++;

}

}

void aud_inout(streaming chanend cin, streaming chanend cout)

{

unsigned int x;

printf("aud_inout() started.\n");

while(1) {

cout <: x;

cin :> x;

}

}

int main(void)

{

streaming chan cin, cout;

printf("main():hello world.\n");

par {

set_audio_thru(cin,cout);

aud_inout(cin,cout);

}

return 0;

}

コード:LEDによるオーディオレベル表示(Audio Level Meter : 1bit)

port led1 = XS1_PORT_1A;

void aud_inout(streaming chanend cin, streaming chanend cout)

{

unsigned int x;

printf("aud_inout() started.\n");

while(1) {

cout <: x;

cin :> x;

a = (x>>8) & 0xFFFFFF;

if (a & 0x800000) {

a = ~a & 0xFFFFFF;

a = a + 1;

}

if (a > 0x180000) led1 <: 1; else led1 <: 0;

}

}

ストリームチャネルを転送している箇所で、オーディオの大きさを確認して、あるしきい値を超えたらLEDを点灯するようにしています。

(StartKITレイアウトのHブロックにあるLED)

DACの違いについて

かくして、Raspberry Pi用のI2Sオーディオ拡張ボードは数種類ありますが、XMOSで

動作させる上で一番大きな違いはMCLK(Master Clock)が必要かどうかという点です。

一般にI2Sで動作するDACの場合、サンプリング周波数fsと同じLRCKと、データ転送に

同期したシリアルデータ用ビットクロックSCLK(BCLK)という64fsのクロックに加えて、

fsの256倍や384倍あるいは512倍の周波数のMCLKの3種類が必須のものが殆どです。

国産の旭化成(AKM)製のDACには電源を入れた状態でクロックを止めてしまうと

発熱し、しまいには壊れてしまうという恐ろしい石もありますが、webで見つかる

Raspberry Pi用のボードはBurr Brown(現TI)製のものWolfson製を搭載した物が殆ど

のようです。

両者ともクロックを止めてしまっても壊れることはありませんが、例えば

S/PDIFレシーバーで外部からデジタル入力する場合などに、Bi-Phase信号から抽出

したクロックをPLLで逓倍する回路を追加しないと、普通のDACは動いてくれませんが

BBのこの石は違います。

近年リリースされたBurr Brown PCM5100シリーズのDACは内部にPLL回路を搭載しているため、

MCLKを与えなくても、GNDレベルにするだけで自分で勝手に必要なクロックを作って

動作してくれるという、AKMには爪のアカでも煎じて呑ませたい位に逞しい石なのです。

想定外な事に弱い日本と、何でもアリな国民性の違いだというには考え過ぎなのでしょうか・・・