void loop() {
// This checks WM8805 status
if (input > 1) {
uint8_t INTSTAT = ReadRegister(wm8805, 11); // poll (and clear) interrupt register;
uint8_t SPDSTAT = ReadRegister(wm8805, 12);
uint8_t SampleRate = (SPDSTAT >> 4) & 0x07;
if (INTSTAT != 0 || SampleRate != SampleRateOld) {
// If something has changed do a screen refresh.
Serial.print("INTSTAT:");Serial.println(INTSTAT,HEX);
Serial.print("SPDSTAT:");Serial.println(SPDSTAT,HEX);
Serial.print("Sample rate:");
switch (SampleRate) {
case 0x03:
Serial.println("32 kHz");
break;
case 0x02:
Serial.println("44 / 48 kHz");
break;
case 0x01:
Serial.println("88 / 96 kHz");
break;
case 0x00:
Serial.println("176/192 kHz");
break;
default:
Serial.println("Unlocked");
break;
}
SampleRateOld = SampleRate;
}
if (SampleRate & 0x04) {
// If this is unlocked then try and switch around normal and 192khz mode
// until it locks. That is kinda hackish but it seems to work.
if (toggle) {
Serial.println("trying 192 kHz mode...");
WriteRegister(wm8805, 6, 8); // set PLL_N to 8
WriteRegister(wm8805, 5, 12); // set PLL_K to 0C49BA (0C)
WriteRegister(wm8805, 4, 73); // set PLL_K to 0C49BA (49)
WriteRegister(wm8805, 3, 186); // set PLL_K to 0C49BA (BA)
//WriteRegister(wm8805, 29, 1); // This might not be needed set SPD_192K_EN to 1
toggle = 0;
} else {
Serial.println("trying normal mode...");
WriteRegister(wm8805, 6, 7); // set PLL_N to 7
WriteRegister(wm8805, 5, 54); // set PLL_K to 36FD21 (36)
WriteRegister(wm8805, 4, 253); // set PLL_K to 36FD21 (FD)
WriteRegister(wm8805, 3, 33); // set PLL_K to 36FD21 (21)
//WriteRegister(wm8805, 29, 0); // This might not be needed set SPD_192K_EN to 0
toggle = 1;
} // if toggle
delay(25); // Give some time for WM8805 to lock
}
}
// This is the IR remote checks
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
switch (results.value) {
case 0x77E15034: //SPDIF1 BNC Input1
if (input == 2) break;
else input = 2;
WriteRegister(wm8805, 8, B00011000); // Select Input 1
break;
case 0x77E16034: //SPDIF2 Coaxial Input2
if (input == 3) break;
else input = 3;
WriteRegister(wm8805, 8, B00011001); // Select Input 2
break;
case 0x77E13034: //SPDIF3 AES Input3
if (input == 4) break;
else input = 4;
WriteRegister(wm8805, 8, B00011010); // Select Input 3
break;
case 0x77E19034: //SPDIF4 Toslink Input4
if (input == 5) break;
else input = 5;
WriteRegister(wm8805, 8, B00011011); // Select RX3
break;
case 0x77E1C034: //Display off
break;
}
irrecv.resume(); //Restart the receiver - Receive the next value
}
}
byte ReadRegister(int devaddr, int regaddr) { // Read a data register value
Wire.beginTransmission(devaddr);
Wire.write(regaddr);
Wire.endTransmission(false); // repeated start condition: don't send stop condition, keeping connection alive.
Wire.requestFrom(devaddr, 1); // only one byte
byte data = Wire.read();
Wire.endTransmission(true);
return data;
}
void WriteRegister(int devaddr, int regaddr, int dataval) { // Write a data register value
Wire.beginTransmission(devaddr); // device
Wire.write(regaddr); // register
Wire.write(dataval); // data
Wire.endTransmission(true);
}
void DeviceInit(int devaddr) { // resets, initializes and powers a wm8805
// reset device
WriteRegister(devaddr, 0, 0);
// REGISTER 7
// bit 7:6 - always 0
// bit 5:4 - CLKOUT divider select => 00 = 512 fs, 01 = 256 fs, 10 = 128 fs, 11 = 64 fs
// bit 3 - MCLKDIV select => 0
// bit 2 - FRACEN => 1
// bit 1:0 - FREQMODE (is written by S/PDIF receiver) => 00
WriteRegister(devaddr, 7, B00000100);
// REGISTER 8
// set clock outputs and turn off last data hold
// bit 7 - MCLK output source select is CLK2 => 0
// bit 6 - always valid => 0
// bit 5 - fill mode select => 1 (we need to see errors when they happen)
// bit 4 - CLKOUT pin disable => 1
// bit 3 - CLKOUT pin select is CLK1 => 0
// bit 2:0 - always 0
WriteRegister(devaddr, 8, B00110000);
// set masking for interrupts
WriteRegister(devaddr, 10, 126); // 1+2+3+4+5+6 => 0111 1110. We only care about unlock and rec_freq
// set the AIF TX
// bit 7:6 - always 0
// bit 5 - LRCLK polarity => 0
// bit 4 - BCLK invert => 0
// bit 3:2 - data word length => 10 (24b) or 00 (16b)
// bit 1:0 - format select: 11 (dsp), 10 (i2s), 01 (LJ), 00 (RJ)
WriteRegister(devaddr, 27, B00001010);
// set the AIF RX
// bit 7 - SYNC => 1
// bit 6 - master mode => 1
// bit 5 - LRCLK polarity => 0
// bit 4 - BCLK invert => 0
// bit 3:2 - data word length => 10 (24b) or 00 (16b)
// bit 1:0 - format select: 11 (dsp), 10 (i2s), 01 (LJ), 00 (RJ)
WriteRegister(devaddr, 28, B11001010);
// set PLL K and N factors
// this should be sample rate dependent, but makes hardly any difference
WriteRegister(devaddr, 6, 7); // set PLL_N to 7
WriteRegister(devaddr, 5, 0x36); // set PLL_K to 36FD21 (36)
WriteRegister(devaddr, 4, 0xFD); // set PLL_K to 36FD21 (FD)
WriteRegister(devaddr, 3, 0x21); // set PLL_K to 36FD21 (21)
// set all inputs for TTL
WriteRegister(devaddr, 9, 0);
// power up device
WriteRegister(devaddr, 30, 0);
// select input
// bit 7 - MCLK Output Source Select => 0 (CLK2)
// bit 6 - Always Valid Select => 0
// bit 5 - Fill Mode Select => 0
// bit 4 - CLKOUT Pin Disable => 1
// bit 3 - CLKOUT Pin Source Select => 1)
// bit 2:0 - S/PDIF Rx Input Select: 000 BNC RX0, 001 Coaxial RX1, 010 AES-ABU RX2, 011 Toshlinkβ RX3, 100 SPDIF-5 RX4, 101 SPDIF-6 RX5, 110 SPDIF-7 RX6, 111 SPDIF-8 RX7
//WriteRegister(devaddr, 8, B00011000); // Select Input 1 (Coax)
}