Skip to content

Instantly share code, notes, and snippets.

@nxzz
Last active June 5, 2019 14:53
Show Gist options
  • Select an option

  • Save nxzz/f750df784f166b82e1f50c43144a872d to your computer and use it in GitHub Desktop.

Select an option

Save nxzz/f750df784f166b82e1f50c43144a872d to your computer and use it in GitHub Desktop.
AK449x fixed PCM
// Wire - Version: Latest
#include <Wire.h>
// 各DACのアドレス
#define AK449X2_J12L_U2_ADDR (0x10) // CAD1 0 CAD2 0 J12 = 2-3 U2
#define AK449X2_J12L_U1_ADDR (0x11) // CAD1 0 CAD2 1 J12 = 2-3 U1
#define AK449X2_J12H_U2_ADDR (0x12) // CAD1 1 CAD2 0 J12 = 1-2 U2
#define AK449X2_J12H_U1_ADDR (0x13) // CAD1 1 CAD2 1 J12 = 1-2 U1
// ボリューム
#define VOL_AD 3 // 可変抵抗を接続するピン ADCが利用可能なAから始まるピンのみ利用可能 3ならA3につなぐ
#define VOL_TH 3 // ADCノイズを吸収するための閾値、ADC値がこの値以上変更された場合に音量が変化する
#define VOL_MIN 150 // ボリュームを最小にした際に設定される値 150で-50dB
#define VOL_MAX 255 // ボリュームを最大にした際に設定される値 255で0dB
// DACのPDNピン
#define DAC_PDN 8 // DACのPDNピン
// 02Hに設定する動作モード
#define DACOUT_STEREO 0b0000
#define DACOUT_MONO_L 0b1000
#define DACOUT_MONO_R 0b1010
// グローバル変数
unsigned int oldVol = 0; // 前回設定した音量
// モード切替用の列挙定数
enum dacmode {
PCM,
DSD64,
DSD128,
DSD256,
DSD512
};
void setup()
{
// GPIO 動作モードを設定
pinMode(DAC_PDN, OUTPUT); // PDN制御用のpinを出力用に設定
// デバッグ用シリアル初期化
Serial.begin(9600);
Serial.print("RUN\n");
// DAC初期化処理
hwResetDac(); // DACをハードリセット
Wire.begin(); // I2C初期化
setmode(PCM); // PCMモードに
}
void loop()
{
// 可変抵抗を読み出す
// unsigned int val = analogRead(VOL_AD);
// 前回設定した音量から、閾値以上の変化がある場合のみ音量を再設定する
// if(abs(val - oldVol) >= VOL_TH){
// oldVol = val;
// Serial.println(map(val, 0, 1023, 0, 255));
// setvol(map(val, 0, 1023, VOL_MIN, VOL_MAX));
// }
}
/*
複数台にレジスタを書き込むラッパー
DACの数やLRに合わせて書き換えること
三つ目の引数はLR選択(0x02の下4bit)
*/
void setmode(enum dacmode mode)
{
// setmode(AK449X2_J12H_U1_ADDR, mode, DACOUT_STEREO);
// setmode(AK449X2_J12L_U1_ADDR, mode, DACOUT_MONO_L); // Lch
// setmode(AK449X2_J12L_U2_ADDR, mode, DACOUT_MONO_R); // Rch
setmode(AK449X2_J12H_U1_ADDR, mode, DACOUT_MONO_L); // Lch
setmode(AK449X2_J12H_U2_ADDR, mode, DACOUT_MONO_R); // Rch
}
/*
複数台に音量設定を書き込むラッパー
DACの数やLRに合わせて書き換えること
*/
void setvol(unsigned int vol)
{
// setvol(AK449X2_J12L_U1_ADDR, vol);
// setvol(AK449X2_J12L_U2_ADDR, vol);
setvol(AK449X2_J12H_U1_ADDR, vol);
setvol(AK449X2_J12H_U2_ADDR, vol);
}
/*
DACをハードリセット
*/
void hwResetDac()
{
digitalWrite(DAC_PDN, LOW);
delay(20);
digitalWrite(DAC_PDN, HIGH);
delay(20);
}
/*
指定アドレスのDACをリセット
*/
void resetDac(unsigned char address)
{
// リセット
Wire.beginTransmission(address);
Wire.write(0x00); // move pointer to control1 address
Wire.write(0x00); // sends 0x00 (hex) 00000000 (binary)
Wire.endTransmission(); // 通信終了
// リセット待ち
delay(20);
}
/*
指定アドレスのDACの指定レジスタに書き込み
*/
void writeDac(unsigned char address, unsigned char regAddr, unsigned char data)
{
// リセット
Wire.beginTransmission(address);
Wire.write(regAddr); // move pointer to control1 address
Wire.write(data); // sends 0x00 (hex) 00000000 (binary)
Wire.endTransmission(); // 通信終了
}
/*
レジスタ設定用
reg2 はMonoMode設定用
MonoMode 未使用時は0b0
Lch は 0b1000
Rch は 0b1010
*/
void setmode(unsigned char address, enum dacmode mode, unsigned char reg2)
{
// リセット
resetDac(address);
switch (mode) {
case PCM:
// PCMモード用のレジスタ
writeDac(address, 0x00, 0b10001111); // 32bit I2S, リセット解除, MCLK 自動検出
writeDac(address, 0x02, 0b00000000 | reg2); // PCMモード
break;
case DSD64:
// DSD64モード用のレジスタ
writeDac(address, 0x00, 0b00000001); // リセット解除
writeDac(address, 0x02, 0b10000000 | reg2); // DSDモード
writeDac(address, 0x06, 0b00000000); // DSD64
writeDac(address, 0x09, 0b00000000); // DSD64
break;
case DSD128:
// DSD128モード用のレジスタ
writeDac(address, 0x00, 0b00000001); // リセット解除
writeDac(address, 0x02, 0b10000000 | reg2); // DSDモード
writeDac(address, 0x06, 0b00000001); // DSD128
writeDac(address, 0x09, 0b00000000); // DSD128
break;
case DSD256:
// DSD256モード用のレジスタ
writeDac(address, 0x00, 0b00000001); // リセット解除
writeDac(address, 0x02, 0b10001000 | reg2); // DSDモード
writeDac(address, 0x06, 0b00010000); // DSD256
writeDac(address, 0x09, 0b00000001); // DSD256
break;
case DSD512:
// DSD512モード用のレジスタ
writeDac(address, 0x00, 0b00000001); // リセット解除
writeDac(address, 0x02, 0b10000000 | reg2); // DSDモード
writeDac(address, 0x06, 0b00000001); // DSD512
writeDac(address, 0x09, 0b00000001); // DSD512
break;
default:
break;
}
}
/*
ボリューム設定
*/
void setvol(unsigned char address, unsigned char vol){
writeDac(address, 0x03, vol); // Lch
writeDac(address, 0x04, vol); // Rch
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment