2022年2月6日日曜日

SNESのAPUへDACを接続する


・関連記事


SNESのAPUへDACを接続する




スーファミに使われているDAC(μPD6376)は、MSBファースト2'sコンプリメントです。
MSBファースト2'sコンプリメントのDACであれば、外付けのDACで音を鳴らすことができます。
サンプリング周波数は約32kHzで、市販されているほとんどのDAC(44.1kHzや48kHz)は使用可能です。



今回は様々なDACを接続してみますが、LPFの設計は行いません。
とりあえずはAPU内のLPFと同じ回路で実験してみると良いでしょう。

一部のDACは、LRCK, BCK, DATAの他に、LRCKの倍の周波数(64kHz)であるWCLKが必要なものがあります。APU内S-DSPから直接配線を出す必要があり、多少面倒です。




PT8211

最近秋月電子で発売されたR2Rラダー型DACです。
低価格 & 8ピンSOPのため、実験用に最適です。
LRCKの最大が384kHz(48kHz x 8 オーバーサンプリング)で、デジタルフィルタが使用可能です。




LC7881

20ピンのDIPで、ブレッドボードでの実験用に最適です。
LRCKの最大が176.4kHz(44.1kHz x 4 オーバーサンプリング)で、デジタルフィルタが使用可能です。
WCLK入力が必要で少し面倒です。





CXD8567AN

秋月電子のお楽しみ袋に入っていた謎DACです。
28ピンのSOPで、x8 オーバーサンプリングデジタルフィルタ付きDACです。
データシートはありませんが、ピン配置はCXD2565Mと似ています。

アッテネータ付きなので電子ボリューム的なことができます。
また、ディエンファシス機能もあるため高音の抑制もできます。
ただし、これらの機能を使うにはシリアルコントロールが必要です。



Arduinoプログラム例
//CXD8567AM_コマンド送信
//©oy
//https://oykenkyu.blogspot.com/2022/02/snes-apu-dac.html

#define MODE2_ATT 0x0000 //アッテネートモード
#define MODE2_SYS 0x0002 //システムモード

//アッテネートモード
#define EMP_EN 0x0004 //ディエンファシス有効
#define MUTE_EN 0x0008 //ミュート状態有効

//システムモード
#define IFORM_LSBF 0x0004 //LSBファースト
#define IFORM_MSBF 0x0000 //MSBファースト

#define IBIT_18 0x0008 //18bit_data
#define IBIT_16 0x0000 //16bit_data

#define MT1_60MS 0x0400 //ゼロデータ検出時間60ms
#define MT1_300MS 0x0000 //ゼロデータ検出時間300ms

#define MT2_HMUTE 0x0800 //ゼロミュートフラグの極性"H"でミュート
#define MT2_LMUTE 0x0000 //ゼロミュートフラグの極性"L"でミュート

#define FS_44_1k 0x0000 //ディエンファシスfs=44.1kHz
#define FS_37_8k 0x1000 //ディエンファシスfs=37.8kHz
#define FS_48_0k 0x2000 //ディエンファシスfs=48.0kHz
#define FS_32_0k 0x3000 //ディエンファシスfs=32.0kHz

#define SYNC_EN 0x4000
#define NSMUTE_EN 0x8000

//シリアルデータ出力
void data_out(unsigned int);

//アッテネートデータ生成(MSB-LSB交換)
unsigned int att_gen(unsigned int);

//セットアップ
void setup()
{
  unsigned int att_data = 0x0400;//アッテネートデータ
  pinMode(2, OUTPUT);  //pin2_att_CXD8567AM(3pin)
  pinMode(3, OUTPUT);  //pin3_shift_CXD8567AM(4pin)
  pinMode(4, OUTPUT);  //pin4_latch_CXD8567AM(5pin)

  digitalWrite(2, LOW);//pin2_att
  digitalWrite(3, LOW);//pin3_shift
  digitalWrite(4, HIGH);//pin4_latch
 
  //アッテネートデータ出力
  data_out(MODE2_ATT | att_gen(att_data));
  //システムデータ出力
  data_out(MODE2_SYS | IFORM_MSBF | IBIT_16 | MT1_300MS | MT2_LMUTE | FS_32_0k);

 
}

void loop()
{
 
}


//シリアルデータ出力
void data_out(unsigned int data){
  digitalWrite(4, HIGH);//pin4_latch
  for (int i = 15;i >= 0;i--){
    digitalWrite(3, LOW);//pin3_shift
    delayMicroseconds(10);
    digitalWrite(2, (data >> i) & 0x01);//pin2_att
    delayMicroseconds(10);
    digitalWrite(3, HIGH);//pin3_shift
    delayMicroseconds(10);
  }
  digitalWrite(4, LOW);//pin4_latch
  delayMicroseconds(10);
  digitalWrite(4, HIGH);//pin4_latch
  delayMicroseconds(10);
}
//アッテネートデータ生成(MSB-LSB交換)
unsigned int att_gen(unsigned int att_data){
  unsigned int ret_data = 0x0000;
  for(int i = 11;i >= 0;i--){
    ret_data |= ((att_data >> i) & 0x0001) << (15-i);
  }
  return ret_data & 0xFFF0;
}












0 件のコメント:

コメントを投稿