PCM179X??????の巻き 2014.5.17
こんなコメントをいただきました。
いままでPCM179Xシリーズで使用したICはPCM1794(24Bit),PCM1795(32Bit)のみですが、TI社から
でているPCM197×シリーズは色々とあります。
すこし、下記に現在リリースされているICについてまとめてみました。
型番 | 分解能 | D-RANGE (dB) |
ピン配置 | 制御 | 価格 (DIGIKEY) |
備考 |
PCM1791 | 24 | 113 | SW可 | 731円 | DSD入力可 | |
PCM1792 | 24 | 132 | SW可 | 1549円 | DSD入力可 PCM1794の S/W制御版? |
|
PCM1793 | 24 | 113 | H/W | 529円 (141個以上) |
PCM1791の HW制御版 |
|
PCM1794 | 24 | 132 | H/W | 2017円 | DSD不可 | |
PCM1795 | 32 | 123 | S/W可 | 918円 | DSD入力可 唯一の32Bit |
|
PC1796 | 24 | 123 | S/W可 | 853円 | DSD入力可 PCM1798の S/W制御版 |
|
PCM1798 | 24 | 123 | H/W | 853円 | DSD不可 |
これだけだとよくわかりませんが、大きくは4つのグループに分かれます。
Dレンジでグループとビット数で分かれますが、それぞれ113dBあるので性能的には問題ありません。
ちなみにDレンジがことなるのは、チップ内部のディジタルフィルターの次数の違いでしょう。
当然次数が多くなると、素子数が増えますからチップの製造コストが高くなります。
グループ | 特徴 | S/W制御 | H/W制御 | 備考 |
1 | 24Bit Dレンジ 113dB | PCM1791 | PCM1793 | |
2 | 24Bit Dレンジ 123dB | PCM1796 | PCM1798 | |
3 | 24Bit Dレンジ 132dB | PCM1792 | PCM1794 | |
4 | 32Bit Dレンジ 123dB | PCM1795 |
シャープロールオフにおける周波数特性
型式 | PCM1791 | PCM1792 |
Dレンジ | 113dB | 132dB |
DF 周波数 特性 |
共通基板? 2014.8.23
基本的にPCM1792,PCM1796,PCM1795はピンコンパチでかつ、コマンドコンパチでもあるので
共通基板としてかけそうです。
SPDIFI、PCM、DSD入力対応です。
こんな感じ?
基板が到着しました。 2014.9.4
検討中のADC4222と同じく、基板ができあがりました。
部品面です。
半田面です。ディジタルとアナログのGNDはICの直下で接続しています。
まずは電源部分の組み立てをおこなって、通電して電圧を確認しておきます。
電源でミスれば部品が全部お釈迦になりかねませんからね。
電源はオペアンプアナログ、DACアナログ、DACディジタルの分離給電が可能ですが、
オペアンプアナログのみの給電ですべてまかなうことも可能です。
オペアンプアナログ電源(15V)→7805(5V)DACアナログ→48M33(3.3V)DACディジタル
で電圧を落としていきます。
電源部分の組み立てと動作の確認です。
どんどん組み立てましょう!
一気に組み立てましょう。
といっても、平日は時間があまりないので作業は亀の歩みです。
休日は休日で出先が多いので、こちらもほとんど時間がとれないので、さらに亀が遅くなっちゃいます(笑)。
まずはICソケット。
表面実装部品をとりつけていきましょう!
今回はPCM1796を使用してみました。
どんどん作りましょう。 2014.9.10
抵抗やコンデンサをどんどん搭載していきましょう。
ほぼ完成です。
今回のオペアンプにはシングルのOPA134Aを使いました。このオペアンプは安価ですが音がいいので気に入っています。
今回はOPA134Aを使いました。
ついでにICも搭載して完成時の雰囲気を味わっています(笑)。
動作確認しましょう。 2014.9.11
PICに最小限のプログラムを書き込んで動作確認をしていきましょう。
CS8416,PCM1796ともI2Cで動作制御しているので、インターフェイスソフトは共通でつかえるので、
プログラムは短くなります。ただ、最終的に電子ボリュームや、入力切替などを組み込むと、それなりに
長くなってしますますが・・・・。たぶんPIC16F819では2kワードのプログラム容量なので、ほぼ一杯に
なってしまうでしょう。
まずはSPDIFモード!
入力にSPDIFから入力してCS8416を使って変換してPC1796を駆動するモードです。
一番シンプルな動作モードでしょう。
SPDIFモードでの動作確認です。
まずは問題なく動くことを確認しました。
波形が出るとホットします。
次はPCMモードで!
PCM信号(DATA,LRCK.、BCK、SCK)の3線制御の出力ソースとしてはFFASRCを用いました。
これを使って44.1〜192kHzでの動作を確認しました。これも問題なく動作を確認できました。
PCMモードでの動作確認の様子です。
最後はDSDモードで!
DSDの出力ソースには、先日試作したADC4222のAD変換ボードを使用しました。
これであれば1本のフラットケーブルで接続できます。
DSD入力での動作確認です。
こちらも問題なく出力が確認できました。
IV抵抗を調整 2014.9.15
オシロの画面をみて少し出力電圧が小さいようです。データシートの回路図の値は820Ωですが、
手元にあった150Ωをつかったのが原因です。ということで、IV抵抗を再調整。
このDACではPCM179Xをパラ使いするので、IV抵抗値は半分の410Ωになりますが、
もっとも近い値である390Ωにいれかえました。
PCM、SPDIFでの出力は丁度いいくらい。
IV抵抗を変更して、再度電源ONです。振幅は2.7V程度(5.4Vpp)なのでほぼ2Vrmsになるので
オーディオ機器の出力としてはピッタシです。
なお、接続はADC4222のPCM出力を接続しています。
振幅2.7V程度ですからほぼ2Vrmsです。
DSD出力は少し低め。
PCM、SPDIFの入力に対してDSD出力は少し低めです。
約半分程度の出力電圧になります。接続はADC4222のDSD出力を接続しています。
ちょうど半分程度の出力になるので、ソフトの問題、ハードの接続の問題等がないか
念のため調べてみましたが、問題ないようでした(パターンを切断してPCM1796からの
出力を個別に調べました)。
DSD出力は少し低め。
このようにDSD出力が低くなる、おそらく次のようなところだとおもいます。PCMは文字通り
パルスコード変調であり、ゼロならびに最大値がはっきり数値として定義できますので、最大値の
入力をすることが簡単です。
それに対してDSDはPDM、すなわちパルス密度変調です。信号レベルをパルス密度で定義するので、
たとえば最大値をHighレベルオンリー、ゼロをLowレベルオンリーとすることができますが、
最大値だけの信号、あるいはゼロレベルだけの信号を送ることはできません(変調信号として成り立たない)。
したがって、どうしても最大値あるいはゼロで定義された振幅の内側での範囲でしか動作することが
できないのだろうとおもいます。そのため、PCM信号で得られる信号振幅の半分程度で動作するのが
自然なところなんでしょう。
試聴してみよう!
今回の試聴のソースは木住野佳子さんのHOPEを引っ張ってきました。
私のお気に入りのアーティストです。この人のピアノを聞いているととても癒されます。
基本はJAZZですので、ペースなどの低音やハイハットの高音も気持ちよくて、試聴にはとても相性がいいです。
でも、やっぱりこの人の弾くピアノが心をうちますね。
試聴に用いたCD
まずはDAC単体
接続は
CDP→(同軸)→DAC179X-2.1→EVC1159(電子ボリューム)→ヘッドホン(オーディオテクニカ
ATH-W10VTG)
という構成です。
まず、最初に音が出たときは、「やっぱりこの人の音楽はいいな〜」という感じです。
まったく試聴にはなってないですね(笑)。
じっくり音楽を聞き入ってしまいます。まず雑味はまったくなく、クリアな音です。
PCM1794によく似ているかな?PCM1794の特徴はダイナミックなヤンチャ坊主の印象ですが、
PCM1796はやや落ち着いた音の印象です。でも、これってソースの雰囲気だったりします(笑)。
オーディオDACとしていい感じです。
まずはSPDIF入力で試聴です。
ちょっとややこしい!
こんどは試作中のADC4222の音質チェックを兼ねて下記の接続にしています。
DAC(PCM61P)→(アナログ)→ADC4222→(PCMorDSD)→DAC179X-2.1
→EVC1159(電子ボリューム)→ヘッドホン(オーディオテクニカ ATH-W10VTG)
です。ディジタル信号をアナログに変換したのち、再度ディジタルに変換してDAC179X-2.1でアナログに戻すという
変換が多い構成です。これで音質の劣化をみてみました。
試聴の時の装置の構成です。
まずはADC4222はPCM出力で。
まずADC4222とPCM179X-2.1とのインターフェイスはPCMとして試聴してみました。最初に音が出たときは、
ほんとにDAC直接で聞いた場合と違いがわからないです。これは、以前にオフミでPCM1804を使ったADCを
介した場合とそうでない場合を聞き比べた場合、差がわからなかったこともありますが、さらに性能の上がった
PCM4222ですから、ますます違いが判らないのでしょう。いづれにしてもPCM4222は十分な性能があるようです。
次はADC4222はDSD出力で。
つぎはADC4222とPCM179X-2.1とのインターフェイスはDSDとして試聴してみました。DSD入力の場合は少し
レベルが下がるので、すこし元気が無いような気がしましたが、レベルを合わせると・・・・
「違いがわからない・・・」という感じです。ややDSDの方がやさしい感じがするかな?というのもDSDはより
アナログに近い信号なので、そうのような音調になるのかもしれません。でも、これって、完全に先入観の
塊ですが(笑)。
IV無しも作ってみました。 2014.9.15
IVアンプ以降を省略した基板も作ってみました。IV抵抗やアンプは外付けになりますが、好みに応じた回路が使用
できるのが特徴です。以前にリリースしたDAC1794-3.5に近い構成です。ただし、今回の基板ではSPDIF入力に加えて、
PCM、DSDの入力が可能なことが特徴です。
v
DAC179X-2.1 SHORTです。
動作チェックにはPCM1795をつかってみました。旧BB社からでているDACの中では唯一の32BitDACです。
さてさて、どんな音がするでしょうね。
この基板ではPCM1795(32Bit)を搭載してみました。
お出かけ用の写真です。
動作確認!
動作確認のためにはIVアンプを接続する必要がありますが、ここは簡単にパッシブIVとしました。
出力に75Ωの抵抗を挟み込みました。
パッシブIVで動作確認です。
まずはSPDIF入力での動作確認です。PICのプログラムについてはPCM1796との互換性を確認するために、
まったく同じモノを書き込んでいます。
SPDIFでの動作確認の様子。
問題なく動いているようです。出力振幅は約600mVあります。
75Ωですから、電流は約8mAです。PCM1795の出力電流は4mAppですから、
パラ接続なので8mAppですから、ピッタシです。
SPDIFでの動作確認をしました。
あわせてPCM入力での確認です。PCM出力はいつものFFASRCを用いています。
FFASRCとの接続でPCM入力も問題ないことを確認しました。
折角なので
急遽 Simple IV for DUAL OPAを組み立てて、接続してみました(定数は手持ちの関係で一部変更しています)。
IVアンプと接続して動作の確認です。
勿論、出力は得られました。
DSDの確認のためにADC4222を接続して接続しました。
DSDでの動作確認です。
やはりPCM1796と同じようにDSDでは出力は少し低くなるようです。
DSDでの出力を確認しました。
プログラムを作成しましょう! 2014.9.18
入力数も少ないので、プログラムは比較的短く書けます。それでもPIC16F819のROM(2kW)の62%を必要としました。
プログラムを組むことで、フィルターの変更も可能になります。下記はPCM1796を使用した場合の基板のフィルタによる
変化です。
ディジタルフィルタ SHARP ROLL OFF SLOW ROLL
OFF
USB-AUDIOとも接続 2014.10.3
エレアトさんのUSB-AUDIOとも接続してDSDの再生を確認しておきました。
エレアトさんUSB-AUDIOとの接続です。
問題なく再生できました。
おまけ機能?
USB-AUDIOはPCMとDSDが同じライン上に出力されますが、USB-AUDIOのP6のPin6に
どちらの出力であるかの信号がでます。Pin6はHならDSD,LならPCMです。これをつかって
DAC1794-X2.1も自動切換えできる機能をおまけ機能でつけくわえました。
たぶん問題ないとはおもいますが・・・。
方法は、あらかじめ、基板のP11(SPD1)とP12(SPD0)をGND接続します。この状態で電源が立ち上がると
USB-AUDIOとの接続であると認識させます。基板のP9にはUSB-AUDIOのPin6(P6)を接続します。
この場合の動作モードは下表の通りです。SPDIF1の入力は使えません。
P9(DSD) USB-AUDIOの Pin6(P6)に接続 |
P10 (PCM) |
P11 (SPD1) |
P12 (SPD0) |
入力選択 |
L(PCM) | OPEN | GND | GND | PCM |
L(PCM) | GND | GND | GND | SPDIF0 |
H(DSD) | OPEN | GND | GND | DSD |
H(DSD) | GND | GND | GND | SPDIF0 |
プログラムはこんな感じです。読めば動作モードがわかる(?)かもしれません。
人の書いたプログラムって癖があって読みにくいんですよね〜。
// // DAC179X-2.1 for DUAL PCM1792/1795/1796 // // (c)OKIRAKU AUDIO / 2014-Sep // // version 1.0 simple use // 2.0 use with USB-AUDIO for electro-art // USB-AUDIO connection Pin6 of P6 into DSD PORT in case of SPD1=SPD0=L // #include "16F819.H" #device ADC=10 #fuses INTRC_IO,NOWDT,PROTECT, NOMCLR,NOBROWNOUT,NOLVP,PUT #use delay(internal=8MHz) #include "math.h" #use fast_io(A) #use fast_io(B) // PCB PIN definition // // INPUT SELECT #define IN_DSD PIN_B0 #define IN_PCM PIN_B1 #define IN_SPDIF1 PIN_B2 #define IN_SPDIF0 PIN_B3 #define NOCHANGE (0) #define DSD_SELECT (1) #define PCM_SELECT (2) #define SPDIF0_SELECT (3) #define SPDIF1_SELECT (4) // JUMPER SETTING #define JP3 PIN_B7 #define JP4 PIN_B6 #define JP5 PIN_B5 #define NOFORMAT (0) #define I2S (1) #define LEFTJ (2) #define RIGHTJ16 (3) #define RIGHTJ24 (4) // JP3,JP4 PCM FORMAT // JP3=H JP4=H I2S // JP3=L JP4=H LEFTJ // JP3=H JP4=L RRIGHJ16 // JP3=L JP4=L RIGHTJ24 // #define SHARPROLL (0) #define SLOWROLL (1) // JP5 DIGITAL FILTER // JP5=H SHARP ROLL OFF // JP5=L SLOW ROLL OFF // // Internal connection define // #define PCM_SEL PIN_A3 #define SPDIF_SEL PIN_A4 #define DSD_SEL PIN_A2 #define I2C_SCL PIN_A6 #define I2C_SDA PIN_A7 #define CS_RST PIN_B4 #define PCM_RST PIN_A1 // I2C ADRS definition #define I2C_CS 0x20 // CS8416 #define PCM_L 0x98 // PCM L channel #define PCM_R 0x9a // PCM R channel #include "i2c.c" // E-VOL variables int UP_DOWN; // E-VOL direction 1:UP 0:Down int16 CurrentEvolAD; // 0 to 1023 int CurrentATT; // 0 to 255 // A/D interface subroutines for PIC int16 get_ad(){ int1 done; int16 value; read_adc(ADC_START_ONLY); done = adc_done(); while(!done) done=adc_done(); value=read_adc(ADC_READ_ONLY); return(value); } int16 get_ad16(int ch){ int16 v; int i; set_adc_channel(ch); // select Volume delay_us(50); v=0; for(i=0;i<16;i++) v+=get_ad(); v= v >> 4; return(v); } TranslateVol(){ int16 n; n=CurrentEvolAD; if(n<=4){CurrentATT = 14;return;} if(n<=102){n*=80;n/=78;n+=10; CurrentATT=(n&0xff);return;} if(n<=514){n/=5;n+=85; CurrentATT=(n&0xff);return;} n-=515; n*=6; n/=45; n+=188; CurrentATT=(n&0xff);return; } int GetVolume(){ int16 v,n; int8 i; v=get_ad16(0); if(v==CurrentEvolAD) return(0); if(UP_DOWN){ // UP MODE if(v > CurrentEvolAD) CurrentEvolAD = v; else if((v+1) < CurrentEvolAD){ CurrentEvolAD = v; UP_DOWN = 0;} } else { // DOWN MODE if(v < CurrentEvolAD) CurrentEvolAD = v; if(v > (CurrentEvolAD+1)){ CurrentEvolAD = v; UP_DOWN = 1;} } return(1); } // CS8416 setting subroutines void cs8416out(int ch,n) {i2c_dataout(I2C_CS,ch,n);} // command out void cs8416_init() // initialize { int i; cs8416out(0x00,0x00); cs8416out(0x01,0x00); cs8416out(0x02,0x0b); cs8416out(0x03,0xb0); cs8416out(0x04,0x98); cs8416out(0x05,0x88); //Right justified 24bit cs8416out(0x06,0x7f); } void cs8416_sel(int ch) // channel selection { int i,j,k; ch &= 7; j=ch; j= j << 3; j &= 0b00111000; j |= ch; k=i=i2c_datain(I2C_CS,0x04); i &= 0xc0; i |= j; if(k!=i) cs8416out(0x04,i); // run and input select } // I/O PORT input/output definition io_select() { output_drive(I2C_SCL); output_high(I2C_SCL); output_float(I2C_SDA); port_b_pullups(0xff); output_high(PCM_SEL); output_drive(PCM_SEL); output_high(SPDIF_SEL); output_drive(SPDIF_SEL); output_high(DSD_SEL); output_drive(DSD_SEL); output_low(CS_RST); output_drive(CS_RST); // CS8416 RESET output_low(PCM_RST); output_drive(PCM_RST); // PCM179X RESET output_float(JP3); output_float(JP4); output_float(JP5); output_float(IN_DSD); output_float(IN_PCM); output_float(IN_SPDIF0); output_float(IN_SPDIF1); setup_adc(ADC_CLOCK_DIV_32); setup_adc_ports(AN0); // ADC OPEN } // status of Input select and jumper int InputStatus() { int i; i=NOCHANGE; if(input(IN_DSD)==0) i=DSD_SELECT; if(input(IN_PCM)==0) i=PCM_SELECT; if(input(IN_SPDIF1)==0) i=SPDIF1_SELECT; if(input(IN_SPDIF0)==0) i=SPDIF0_SELECT; return(i); } int InputStatusUSB() { int i; i=NOCHANGE; if(input(IN_PCM)==0){ if(input(IN_DSD)) i=DSD_SELECT; else i=PCM_SELECT; } else i=SPDIF0_SELECT; return(i); } int FormatStatus() { int i,i3,i4; i3=input(JP3); i4=input(JP4); if(i3 && i4 ) i=I2S; // I2S if(i3==0 && i4 ) i=LEFTJ; // LJ if(i3 && i4==0 ) i=RIGHTJ16; // RJ16 if(i3==0 && i4==0 ) i=RIGHTJ24; // RJ24 return(i); } int FilterStatus() { int i; if(input(JP5)) i=SHARPROLL; // SHARP else i=SLOWROLL; return(i); } main() { int InputSelect; int FilterSelect; int FormatSelect; int usbdac; int i,j,k,f; io_select(); // IO initialize delay_ms(500); // wait power up output_high(CS_RST); // resset inactive output_high(PCM_RST); delay_ms(100); // wait cs8416_init(); // cs8416 initialize UP_DOWN=1; CurrentEvolAD=0; CurrentATT=0; // initial settting // INPUT:SPDIF0, RJ24, SHARP ROLLOFF, VOL=0(MUTE) output_high(DSD_SEL); output_high(PCM_SEL); output_low(SPDIF_SEL); delay_ms(20); cs8416_sel(0); // default select ch.0 i2c_dataout(PCM_L,18,0xa0); // RJ24 i2c_dataout(PCM_L,19,0x00); // SHARP ROLL OFF i2c_dataout(PCM_L,20,0x08); // PCM MONO L i2c_dataout(PCM_L,21,0x01); // NORMAL RUN i2c_dataout(PCM_R,18,0xa0); // RJ24 i2c_dataout(PCM_R,19,0x00); // SHARP ROLL OFF i2c_dataout(PCM_R,20,0x0c); // PCM MONO R i2c_dataout(PCM_R,21,0x01); // NORMAL RUN i2c_dataout(PCM_L,16,0); // initial MUTE i2c_dataout(PCM_R,16,0); i2c_dataout(PCM_L,17,0); i2c_dataout(PCM_R,17,0); InputSelect=SPDIF0_SELECT; FilterSelect=SHARPROLL; FormatSelect=RIGHTJ24; usbdac=0; if(input(IN_SPDIF0)==0 && input(IN_SPDIF1)==0) usbdac=1; // ELECTRO-ART USB AUDIO ACTIVE while(1){ if(usbdac) i=InputStatusUSB(); else i=InputStatus(); if((i!=NOCHANGE) && i!=InputSelect){ switch(i){ case DSD_SELECT: output_high(SPDIF_SEL); output_high(PCM_SEL); output_low(DSD_SEL); delay_ms(20); i2c_dataout(PCM_L,20,0x28); i2c_dataout(PCM_R,20,0x2c); InputSelect=i; break; case PCM_SELECT: output_high(DSD_SEL); output_high(SPDIF_SEL); output_low(PCM_SEL); delay_ms(20); if(InputSelect==DSD_SELECT){ i2c_dataout(PCM_L,20,0x08); i2c_dataout(PCM_R,20,0x0c); } InputSelect=i; break; case SPDIF1_SELECT: case SPDIF0_SELECT: output_high(DSD_SEL); output_high(PCM_SEL); output_low(SPDIF_SEL); delay_ms(20); if(InputSelect==DSD_SELECT){ i2c_dataout(PCM_L,20,0x08); i2c_dataout(PCM_R,20,0x0c); } if(i==SPDIF0_SELECT) cs8416_sel(0); else cs8416_sel(1); InputSelect=i; f=0xa0; // RJ24 i2c_dataout(PCM_L,18,f); i2c_dataout(PCM_R,18,f); FormatSelect=RIGHTJ24; break; default:break; } } i=FormatStatus(); if((i!=FormatSelect)&&(InputSelect==PCM_SELECT)){ switch(i){ case I2S: f=0xd0; break; // I2S case LEFTJ: f=0xb0; break; // LJ case RIGHTJ16: f=0x80; break; // RJ16 case RIGHTJ24: f=0xa0; break; // RJ24 default:break; } i2c_dataout(PCM_L,18,f); i2c_dataout(PCM_R,18,f); FormatSelect=i; } i=FilterStatus(); if((i!=FilterSelect)&&(InputSelect!=DSD_SELECT)){ if(i==SHARPROLL){ i2c_dataout(PCM_L,19,0x00); i2c_dataout(PCM_R,19,0x00); } else { i2c_dataout(PCM_L,19,0x02); i2c_dataout(PCM_R,19,0x02); } FilterSelect=i; } i=GetVolume(); if(i){ i=CurrentATT; TranslateVol(); if(i!=CurrentATT){ i= CurrentATT; i2c_dataout(PCM_L,16,i); i2c_dataout(PCM_R,16,i); i2c_dataout(PCM_L,17,i); i2c_dataout(PCM_R,17,i); } } } }
(つづく?)