Last active
June 5, 2019 14:53
-
-
Save nxzz/f750df784f166b82e1f50c43144a872d to your computer and use it in GitHub Desktop.
AK449x fixed PCM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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