- 21 January 2007
- 21,629
BuffaloCon
Μιας και μια έγχρωμη TFT καθυστερεί να φτάσει στα χέρια και έχω βαρεθεί να περιμένω…
Είπα να πιάσω τον κώδικα του DimDim http://www.avclub.gr/forum/showthre...-Sabre-ES9018-based-DACs-(Buffalo-32s-II-III) και να τον μετατρέψω ώστε η επικοινωνία να γίνεται μέσω της σειριακής θύρας επικοινωνίας που έχει το arduino.
Σίγουρα έχω αφήσει πολύ άχρηστο κώδικα από τις δύο προηγούμενες υλοποιήσεις στις οποίες βασίστηκα, ενώ θα γίνουν προσθήκες, κυνηγητό Bugs κ.ο.κ.
Για την ώρα πάντως παίζει.
Κλικιτι κλικ
Hardware Setup:
PC -> USB -> Arduino
Arduino pins SCLK, SDA, GND -> Buffalo pins SCLK, SDA, GND (i2c header, remove original IC)
Σημείωση
Το arduino όταν είναι συνδεδεμένο με USB, δίνει πρόσβαση σε μια (ιδεατή) σειριακή θύρα Μέσω της οποίας έχουμε αμφίδρομη επικοινωνία.
Θετικά:
Δεν απαιτείται καμία οθόνη πέραν του υπολογιστή σας. ( μια καλή LCD οθόνη μη ξεχνάμε ότι κάνει ~$40)
Πρόσβαση σε όλες τις δυνατότητες προγραμματισμού του ESS Sabre32.
Ένα καλώδιο usb για τροφοδοσία του arduino και αμφίδρομη επικοινωνία μέσω serial.
Το βουβάλι προσωπικά το έχω για ‛κάρτα ήχου’ με το PC πάντα ανοιχτό σα πηγή. Όποτε με βολεύει να έχω όλα τα controls εκεί διαθέσιμα. Κάτι σαν το interface που δίνουν οι επαγγελματικές κάρτες ήχου, με ενδείξεις για όλες τις λειτουργίες και την πραγματική κατάσταση.
Πολύ απλό Keyboard Interface:
<key>:<command>
f:FIR, i : IIR, q : Quantizer, d : DPLL, n : Notch, p : DPLLMode, o : OSF
keys 1 to 8:select input 1 to 8
keys + -:volume up/down
Screen Capture:
Μιας και μια έγχρωμη TFT καθυστερεί να φτάσει στα χέρια και έχω βαρεθεί να περιμένω…
Είπα να πιάσω τον κώδικα του DimDim http://www.avclub.gr/forum/showthre...-Sabre-ES9018-based-DACs-(Buffalo-32s-II-III) και να τον μετατρέψω ώστε η επικοινωνία να γίνεται μέσω της σειριακής θύρας επικοινωνίας που έχει το arduino.
Σίγουρα έχω αφήσει πολύ άχρηστο κώδικα από τις δύο προηγούμενες υλοποιήσεις στις οποίες βασίστηκα, ενώ θα γίνουν προσθήκες, κυνηγητό Bugs κ.ο.κ.
Για την ώρα πάντως παίζει.
Κλικιτι κλικ
Code:
/**************************************************************************************************
* BuffaloCon Code: My adaptation of the TFT HIFIDUINO code for Serial Port
*
* v.00.01 11/04/12 : - Initial Implementation
* - Lots of unused variables from previous projects need to be removed
* - Extra timer in main loop prints every INTERVAL some text
*
* The bellow comments (be HIFIDUINO or TFT HIFIDUINO) sill largelly apply
*
* Getting Started:
* - Open a Serial connection to COM<X> where your arduino is connected. Use putty or any other sw.
* - Wait for the banners to apear, Press ? key for Help
***************************************************************************************************/
/**************************************************************************************************
* TFT HIFIDUINO Code: My adaptation of the HiFiDUINO code so that is displays on a colour TFT.
*
* v.0.51 11/03/12 : - Contains a few minor bugs but for the most part works.
* - Includes support of source selection on Buffalo III boards.
* - The Apple remote codes are changed to another device's that I had handy.
* - Has not been tested with I2S sources.
*
* The below comments (be HIFIDUINO) still largely apply.
*
***************************************************************************************************/
/***************************************************************************************************
* HIFIDUINO Code: Supports Buffalo II 80Mhz and 100Mhz, stereo and dual mono.
*
* Change log:
* v. B1.0b 01/07/12:- Compatible with Arduino 1.0 (but not backward compatible)
* - Fixed Minor (potential) bugs
* - Two additional settings: Oversampling bypass and jitter eliminator bypass
* ...NOTE COMMENTS REMOVED...
***************************************************************************************************/
/***************************************************************************************************
* Code starts here
***************************************************************************************************/
// LIBRARIES
#include <Wire.h> // For I2C
#include <EEPROM.h> // We will use the eeprom to store values
// CONSTANT DEFINITION
/******************* Code Customization Section *********************/
/* First: Choose the clock frequency you have and comment the other */
#define USE80MHZ
//#define USE100MHZ
/* Second: Choose your configuration
| CONFIGURATION | #define DUALMONO | #define TPAPHASE |
|---------------------|------------------|------------------|
| Dual mono in-phase | un-comment | comment |
| Dual mono TPA phase | un-comment | un-comment |
| Stereo | comment | comment |
|---------------------|------------------|------------------| */
//#define DUALMONO
//#define TPAPHASE
/* Optionally choose the number of inputs. 6 is the max without
modifying the code. You could lower the number of input choices
here */
#define ICHO 8
/* Optionally change the name of the inputs. Use blanks if necessary */
char no0[] = "COAX 1";
char no1[] = "OPT 1";
char no2[] = "OPT 2";
char no3[] = "AES/EBU";
char no4[] = "COAX 2";
char no5[] = "COAX 3";
char no6[] = "I2S 1";
char no7[] = "I2S 2";
/* Make sure you use the correct chip address for each board
for stereo Buffalo: use address 0x90
for dual mono: Use address 0x90 for mono left Buffalo
Use address 0x92 for mono right Buffalo */
/********************************************************************/
#define DEFAULTATTNU 0x04 //-50 dB this is 50x2=100 or 0x64. Sabre32 is 0 to -127dB in .5dB steps
#define MAXATTNU 0xC6 //-99dB this is 99X2=198 or 0xC6 -Can go higher but LCD shows 2 digits
#define MINATTNU 0x00 //-0 dB -Maximum volume is -0 dB
#define DIM 0x8C //-70 dB this is 70x2=140 or 0x8C. Dim volume
#define RAMP 10 // Additional msec delay per 1 db for ramping up to volume after dim
#define VOLUPPIN 4 // Button to increase volume or RotEnc A terminal
#define VOLDOWNPIN 2 // Button to decrease volume or RotEnc B terminal
#define SELECTPIN 5 // Switch to select function
// #define BRIPIN 6 // Pin to control the LCD brightness with analogWrite
#define REMOTEPIN 9 // Pin for IR receiver (remote control)
#define INTERVAL_SAMPLE 2 // Time interval in SECONDS for refreshing the sample rate
#define INTERVAL_BOUNCE 2 // Time in milliseconds to debounce the rotary encoder
#define INTERVAL_SWITCHBOUNCE 200 // Time in milliseconds to debounce switch
#define INTERVAL_SELECT 4 // Time in sec to exit select mode when no activity
#define VOL 0 // The order of selection when clicking the select switch
#define FIR 3 // FIR filter selection
#define IIR 4 // IIR filter selection
#define QTZ 6 // Quantizer selection
#define INP 1 // Input selection
#define INF 2 // Input format selection
#define DPL 5 // DPLL bandwidth setting
#define NCH 7 // Notch selection
#define PLM 8 // DPLL mode
#define OSF 9 // Oversampling
#define B 0xFF // The character for a completely filled box
#define A 0x20 // The character for blank
// Order of settings in the array for each input
#define FORMATVAL 0
#define FIRVAL 1
#define IIRVAL 2
#define DPLLVAL 3
#define QUANVAL 4
#define NOTCHVAL 5
#define PLMVAL 6
// Number of valid choices for each parameter
// There is one more: ICHO defined above
#define FORMATCHO 2 // SPDIF, I2S/DSD
#define FIRCHO 2 // Fast, slow
#define IIRCHO 4 // PCM, 50k, 60k, 70k
#define DPLLCHO 8 // Lowest to Best 8 values
#define QUANCHO 6 // 6bT, 7bP, 7bT, 8bP, 8bT, 9bP
#define NOTCHCHO 6 // /4 to /64
#define PLMCHO 3 // Normal x1 (NOR), Multiplier x128 (MUL), Bypass (OFF)
#define MAXPARAM 8 // Total number of parameters to keep track for each input. The 8th is for OSF
// But we don't keep track of that. It always starts with Oversampling on and
// the function is a toggle (on/off). This is why there is no "OSFCHO"
// VARIABLE DECLARATION
// Register variables: used for registers that have lots of options. They are initialized here
// with valid values, but will eventually be overwritten by the values in EEPROM
byte reg14=0xF9; // Default value for register 14. We use a variable for reg 14 because it controls
// several parameters: IIR, FIR, differential whereas the other registers typically
// controls a single parameter.
byte reg25=0; // 0= allow all settings
byte reg17L=0x1C; // Auto SPDIF, 8-channel mode, other defaults
// reg17L is used for stereo and for left channel if set for MONO
#ifdef DUALMONO
byte reg17R=0x9D; // Auto SPDIF, MONO RIGHT CHANNEL, other defaults
#endif DUALMONO
byte reg10=0xCE; // jitter ON, dacs unmute, other defaults
unsigned long displayMillis = 0; // Stores last recorded time for display interval
unsigned long debounceMillis = 0; // Stores last recorded time for switch debounce interval
unsigned long selectMillis = 0; // Stores last recorded time for being in select mode
unsigned long sr = 0; // Stores the incoming sample rate. Used for auto OSF bypass for 80MHz crystal
byte input=0; // The current input to the DAC
byte currAttnu=DEFAULTATTNU; // Variable to hold the current attenuation value
byte select; // To record current select position (FIL, VOL, DPLL, etc)
boolean selectMode; // To indicate whether in select mode or not
boolean SPDIFValid; // To indicate whether SPDIF valid data
boolean spdifIn; // To indicate whether in I2S/DSD or SPDIF input format mode
boolean bypassOSF=false; // false=no bypass; This is the default condition at startup
boolean primed=false; // To indicate if dpll has been conditioned (once at startup)
boolean dimmed=false; // To indicate dim (mute) or not
byte pulse=0; // Used by the "heartbeat" display
byte Status; // To hold value of Sabre32 status register
byte StatusS; // To hold value of Sabre32 SPDIF status register
// The following variables for the new s/pdif info feature
boolean pro_cons;
boolean samp1;
boolean samp2;
boolean samp3;
boolean samp4;
boolean bitd1;
boolean bitd2;
boolean bitd3;
boolean bitd4;
// The array holds the parameters for each input
// The current input is recorded after the array
byte settings[ICHO][MAXPARAM]; // Array to hold parameter values
void writeSettings(){
for(byte i=0;i<ICHO;i++) {
for (byte j=0;j<MAXPARAM;j++) {
EEPROM.write((i*MAXPARAM)+j,settings[i][j]);
}
}
EEPROM.write(ICHO*MAXPARAM,input); // Write the current input in a variable location after the array
}
void readSettings(){
for(byte i=0;i<ICHO;i++) {
for (byte j=0;j<MAXPARAM;j++) {
settings[i][j]=EEPROM.read((i*MAXPARAM)+j);
}
}
input=EEPROM.read(ICHO*MAXPARAM); // Read the last saved input setting
}
/*
READING THE SAMPLE RATE
The sample rate can be calculated by reading the DPLL 32-bit register. For SPDIF DPLL value
is divided by (2^32/Crystal-Frequency). In Buffalo II (original), the Crystal frequency is
80,000,000 Hz. In Arduino (and other small microprocessors) it is NOT advisable to do floating point
math because "it is very slow"; therefore integer math will be used to calculate the sample rate.
The value of 2^32/80,000,000 is 53.687091 (which is a floating point number). If we use the
integer part (53 or 54) we get the following results for a 44.1K sample rate signal: divided by 53
the result is 44.677K; divided by 54, the result is 43.849K. Clearly there are large errors from
being confined to integer math. The actual result, if we use floating point math and use all the
significant digits is 44,105 Hz (the 5 Hz deviation from ideal 44100 Hz is within the specification
of SPDIF and the tolerances of the crystals and clocks involved)
In order to increase the accuracy of the integer calculation, we can use more of the significant
digits of the divisor. I did some evaluation of the DPLL register values for sample rates ranging
from 44.1K to 192K and noticed that I could multiply the value of the DPLL number by up to
400 without overflowing the 32-bits. Therefore, since we have 32 bit number to work with, we
can multiply the DPLL number by up to 400 and then divide by 400X53.687091=21475. If we do this,
we obtain 44.105K which is the same as the exact value.
I used a spreadsheet to calculate the multipliers for SPDIF and I2S and for both 80Mhz and 100Mhz
SPDIF 80Mhz: x80, %4295
SPDIF 100Mhz: x20, %859
I2S 80Mhz: x1, %3436
I2S 100Mhz: x4, %10995 (higher multiplier will overflow the 32bit value for 384KHz SR)
x5, %13744 (More accurate but only works up to 192KHz SR)
For I2S input format the dpll number is divided by (2^32*64/Crystal-Frequency) Note the 64 factor.
The value of this is 3435.97 which rounds off nicely to 3436 (which is only 0.0008% error). The
resultant value for the sample rate is the same wheter in spdif or I2S mode.
*/
// Sample rate reading routines
volatile unsigned long DPLLNum; // Variable to hold DPLL value
byte readDPLL(byte regAddr) {
Wire.beginTransmission(0x48); // Hard coded the Sabre/Buffalo device address
Wire.write(regAddr); // Queues the address of the register
Wire.endTransmission(); // Sends the address of the register
Wire.requestFrom(0x48,1); // Hard coded to Buffalo, request one byte from address
// specified with Wire.write()/wire.endTransmission()
//while(!Wire.available()) { // Wait for byte to be available on the bus
if(Wire.available()) // Wire.available indicates if data is available
return Wire.read(); // Wire.read() reads the data on the wire
else
return 0; // In no data in the wire, then return 0 to indicate error
}
unsigned long sampleRate() {
DPLLNum=0;
// Reading the 4 registers of DPLL one byte at a time and stuffing into a single 32-bit number
DPLLNum|=readDPLL(31);
DPLLNum<<=8;
DPLLNum|=readDPLL(30);
DPLLNum<<=8;
DPLLNum|=readDPLL(29);
DPLLNum<<=8;
DPLLNum|=readDPLL(28);
// The following calculation supports 80 MHz oscillator
if (SPDIFValid){
#ifdef USE80MHZ
DPLLNum*=80; // Calculate SR for SPDIF -80MHz part
DPLLNum/=4295; // Calculate SR for SDPIF -80MHz part
#endif
#ifdef USE100MHZ
DPLLNum*=20; // Calculate SR for SPDIF -100MHz part
DPLLNum/=859; // Calculate SR for SDPIF -100MHz part
#endif
}
else { // Different calculation for SPDIF and I2S
#ifdef USE80MHZ
DPLLNum/=3436; // Calculate SR for I2S -80MHz part
#endif
#ifdef USE100MHZ
DPLLNum*=4; // Calculate SR for I2S -100MHz part
DPLLNum/=10995; // Calculate SR for I2S -100MHz part
#endif
}
if(bypassOSF) // When OSF is bypassed, the magnitude of DPLL is reduced by a factor of 64
DPLLNum*=64;
return DPLLNum;
}
// Reading the status register. There is a status register providing the following information:
// 1- dsd or pcm mode
// 1- spdif valid or invalid
// 3- spdif mode enabled or disabled.
// 4- Jitter Eliminator locked/not locked to incoming signal
byte readStatus() { // Hardcoded to the status register
Wire.beginTransmission(0x48); // Hard coded the Sabre/Buffalo device address
Wire.write(27); // Hard coded to status register
Wire.endTransmission();
Wire.requestFrom(0x48,1); // Hard coded to Buffalo, request one byte from address
// specified with Wire.write()
//while(!Wire.available()) { // Wait for byte to be available on the bus
if(Wire.available())
return Wire.read(); // Return the value returned by specified register
else
return 0;
}
// Reading the SPDIF status register. There is a status register providing the following information:
// 1- dsd or pcm mode
// 1- spdif valid or invalid
// 3- spdif mode enabled or disabled.
// 4- Jitter Eliminator locked/not locked to incoming signal
byte readSPDIFStatus() { // Hardcoded to the status register
Wire.beginTransmission(0x48); // Hard coded the Sabre/Buffalo device address
Wire.write(48); // Hard coded to status register
Wire.endTransmission();
Wire.requestFrom(0x48,1); // Hard coded to Buffalo, request one byte from address
// specified with Wire.write()
//while(!Wire.available()) { // Wait for byte to be available on the bus
if(Wire.available())
return Wire.read(); // Return the value returned by specified register
else
return 0;
}
/*
CONTROLLING THE DIGITAL ATTENUATION (VOLUME) -and other registers IN THE DAC
The device address of Sabre DAC Datasheet specifies the address as 0x90 which is an 8-bit value.
The wire library in Arduino uses 7-bit device addresses and the 8th R/W bit is added automatically
depending on whether you use the write call [beginTransmission()] or the read call [requestFrom()].
Therefore, you will use the 7 most significant bits of the 8-bit address.
In our example, 0x90 becomes 0x48 as follows:
0x90: 10010000 (we eliminate the rightmost bit to get I2C address)
0x48: 1001000
When using dual-mono configuration, the other device can be set to addres 0x92
0x92: 10010010 (we eliminate the rightmost bit to get I2C address)
0x49: 1001001
*/
void writeSabreReg(byte regAddr, byte regVal)
{
Wire.beginTransmission(0x48); //Hard coded to the the Sabre/Buffalo device address
Wire.write(regAddr); // Specifying the address of register
Wire.write(regVal); // Writing the value into the register
Wire.endTransmission();
#ifdef DUALMONO
Wire.beginTransmission(0x49); //Hard coded to the the other Sabre/Buffalo device address
Wire.write(regAddr); // Specifying the address of register
Wire.write(regVal); // Writing the value into the register
Wire.endTransmission();
#endif DUALMONO
}
void setSabreVolume(byte regVal)
{
writeSabreReg(0, regVal); // set up volume in DAC1
writeSabreReg(1, regVal); // set up volume in DAC2
writeSabreReg(2, regVal); // set up volume in DAC3
writeSabreReg(3, regVal); // set up volume in DAC4
writeSabreReg(4, regVal); // set up volume in DAC5
writeSabreReg(5, regVal); // set up volume in DAC6
writeSabreReg(6, regVal); // set up volume in DAC7
writeSabreReg(7, regVal); // set up volume in DAC8
}
void rampUp()
{
byte i=(DIM-currAttnu);
for(byte dimval=DIM;dimval>currAttnu;dimval--){
setSabreVolume(dimval);
// tft.setRotation(3);
// tft.setCursor(130, 100);
// tft.setTextColor(vol_color);
// tft.setTextSize(6);
// tft.setRotation(3);
// tft.fillRoundRect(130, 100, 200, 60, 0, vol_back_col);
// tft.print("-");
// tft.print(dimval/2);
// tft.println("dB");
Serial.print("-");
Serial.print(dimval/2);
Serial.print("dB");
delay((RAMP)*(1+(10/i*i)));
i--;
}
}
// Because of register 17 sets MONO/8-channel, different values are written into different chips
void writeSabreLeftReg(byte regAddr, byte regVal)
{
Wire.beginTransmission(0x48); // Hard coded to the the Sabre/Buffalo device address for stereo
// or mono left. For stereo same as writeSabreReg()
Wire.write(regAddr); // Specifying the address of register
Wire.write(regVal); // Writing the value into the register
Wire.endTransmission();
}
#ifdef DUALMONO
void writeSabreRightReg(byte regAddr, byte regVal)
{
Wire.beginTransmission(0x49); //Hard coded to the the Sabre/Buffalo device address
Wire.write(regAddr); // Specifying the address of register
Wire.write(regVal); // Writing the value into the register
Wire.endTransmission();
}
#endif DUALMONO
/*
The following function prints a bar at the left most column to indicate that we are in "select"
mode. One can choose any character as the "bar" For example, I used the solid square character
*/
void printSelectBar(){
Serial.print("---printSelectBar");
}
void removeSelectBar(){
Serial.print("---removeSelectBar");
}
void setAndPrintDPLL(byte value){
Serial.print("DPLL B/W: ");
switch(value){
case 0:
bitSet(reg25,1); // Reg 25: set bit 1 for "use best dpll"
writeSabreReg(0x19,reg25); // Write value into reg 25 for best dpll
Serial.println("Auto");
break;
case 1:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x85); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("Lowest");
break;
case 2:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x89); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("Low");
break;
case 3:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x8D); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("Low-Med");
break;
case 4:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x91); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("Medium");
break;
case 5:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x95); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("Med-High");
break;
case 6:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x99); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("High");
break;
case 7:
bitClear(reg25,1); // Reg 25: Clear bit 1 for "use all settings"
writeSabreReg(0x19,reg25); // Write value into reg 25 for all settings
writeSabreReg(0x0B,0x9D); // Reg 11: Set corresponding DPLL bandwidth
Serial.println("Highest");
break;
}
}
void setAndPrintDPLLMode(byte value){ // Set the DPLL Mode
Serial.print("DPLL Mode:");
switch(value){
case 0:
bitSet(reg10,3); // Set bit 3 of reg 10: jitter reduction ON
writeSabreReg(0x0A,reg10);
bitSet(reg25,0); // Set bit 0 of reg 25 for x128 DPLL bandwidth
writeSabreReg(0x19,reg25);
Serial.println("x128");
break;
case 1:
bitSet(reg10,3); // Set bit 3 of reg 10: jitter reduction ON
writeSabreReg(0x0A,reg10);
bitClear(reg25,0); // Clear bit 0 of reg 25 for x1 DPLL bandwidth
writeSabreReg(0x19,reg25);
Serial.println("x1");
break;
case 2:
bitClear(reg10,3); // Clear bit 3 of reg 10: jitter reduction bypass
writeSabreReg(0x0A,reg10);
Serial.println("NOS");
break;
}
}
void setAndPrintBypassOSF(){ // This is just a toggle function
if(bypassOSF==true){
bypassOSF=false;
bitClear(reg17L,6); // Reg 17: clear bypass oversampling bit in register
writeSabreLeftReg(0x11,reg17L); // Reg 17: bypass OSF off
#ifdef DUALMONO
bitClear(reg17R,6); // Reg 17: clear bypass oversampling bit in register -dual mono
writeSabreRightReg(0x11,reg17R); // Reg 17: bypass OSF off
#endif DUALMONO
Serial.print("Over/ling:"); // Indicate oversampling is ON (^)
Serial.print("On");
}
else {
bypassOSF=true;
bitSet(reg17L,6); // Reg 17: set bypass oversampling bit in register
writeSabreLeftReg(0x11,reg17L); // Reg 17: bypass OSF on
#ifdef DUALMONO
bitSet(reg17R,6); // Reg 17: set bypass oversampling bit in register -dual mono
writeSabreRightReg(0x11,reg17R); // Reg 17: bypass OSF on
#endif DUALMONO
Serial.print("Over/ling:"); // Indicate no oversampling (.)
Serial.println("Off");
}
}
void setAndPrintFirFilter(byte value){
Serial.print("Filter:");
switch(value){
case 0:
bitSet(reg14,0); // Set bit 0 of reg 14 for sharp fir
writeSabreReg(0x0E,reg14);
Serial.println("Sharp FIR");
break;
case 1:
bitClear(reg14,0); // Clear bit 0 of reg 14 for slow fir
writeSabreReg(0x0E,reg14);
Serial.println("Slow FIR");
break;
}
}
void setAndPrintIirFilter(byte value){
Serial.print("IIR:");
//tft.setCursor(10, 32);
switch(value){
case 0: // | | | | | |0|0| | IIR Bandwidth: Normal (for PCM)
bitClear(reg14,1); // Clear bit 1
bitClear(reg14,2); // Clear bit 2
writeSabreReg(0x0E,reg14);
Serial.println("PCM");
break;
case 1: // | | | | | |0|1| | IIR Bandwidth: 50k (for DSD) (D)
bitSet(reg14,1); // Set bit 1
bitClear(reg14,2); // Clear bit 2
writeSabreReg(0x0E,reg14);
Serial.print("50K");
break;
case 2: // | | | | | |1|0| | IIR Bandwidth: 60k (for DSD)
bitSet(reg14,2); // Set bit 2
bitClear(reg14,1); // Clear bit 1
writeSabreReg(0x0E,reg14);
Serial.println("60K");
break;
case 3: // | | | | | |1|1| | IIR Bandwidth: 70k (for DSD)
bitSet(reg14,1); // Set bit 1
bitSet(reg14,2); // Set bit 2
writeSabreReg(0x0E,reg14);
Serial.println("70K");
break;
}
}
void setAndPrintQuantizer(byte value){
Serial.print("Qtz:");
switch(value){
case 0: // 6-bit true diff
bitSet(reg14,3); // True differential
writeSabreReg(0x0E,reg14);
writeSabreReg(0x0F,0x00); // 6-bit quantizer
Serial.println("6bT");
break;
case 1: // 7-bit pseudo diff
bitClear(reg14,3); // Pseudo diff
writeSabreReg(0x0E,reg14);
writeSabreReg(0x0F,0x55); // 7-bit quantizer
Serial.println("7bP");
break;
case 2: // 7-it true diff
bitSet(reg14,3); // True differential
writeSabreReg(0x0E,reg14);
writeSabreReg(0x0F,0x55); // 7-bit quantizer
Serial.println("7bT");
break;
case 3: // 8-bit pseudo diff
bitClear(reg14,3); // Pseudo diff
writeSabreReg(0x0E,reg14);
writeSabreReg(0x0F,0xAA); // 8-bit quantizer
Serial.println("8bP");
break;
case 4: // 8-bit true diff
bitSet(reg14,3); // True differential
writeSabreReg(0x0E,reg14);
writeSabreReg(0x0F,0xAA); // 8-bit quantizer
Serial.println("8bT");
break;
case 5: // 9-bit pseudo diff
bitClear(reg14,3); // Pseudo diff
writeSabreReg(0x0E,reg14);
writeSabreReg(0x0F,0xFF); // 9-bit quantizer
Serial.println("9bP");
break;
}
}
void setAndPrintNotch(byte value){
Serial.print("Notch:");
switch(value){
case 0:
writeSabreReg(0x0C,0x20); // No notch delay
Serial.println("NON");
break;
case 1:
writeSabreReg(0x0C,0x21); // notch delay=mclk/4
Serial.println("/04");
break;
case 2:
writeSabreReg(0x0C,0x23); // notch delay=mclk/8
Serial.println("/08");
break;
case 3:
writeSabreReg(0x0C,0x27); // notch delay=mclk/16
Serial.println("/16");
break;
case 4:
writeSabreReg(0x0C,0x2F); // notch delay=mclk/32
Serial.println("/32");
break;
case 5:
writeSabreReg(0x0C,0x3F); // notch delay=mclk/64
Serial.println("/64");
break;
}
}
void setAndPrintInputFormat(byte value){
// This register also controls mono-8channel operation, thus more code...
Serial.print("Input:");
switch(value){
case 0:
writeSabreReg(0x08,0xE8); // Reg 8: Enable SPDIF input format
bitSet(reg17L,3); // Reg 17: auto spdif detection ON -Set bit 3
writeSabreLeftReg(0x11,reg17L); // Reg 17: write value into register
#ifdef DUALMONO
bitSet(reg17R,3); // Reg 17: auto spdif detection ON -Set bit 3
writeSabreRightReg(0x11,reg17R); // Reg 17: write value into register
#endif DUALMONO
spdifIn=true; // Indicates input format is spdif. For label for input format
Serial.println("S/PDIF");
break;
case 1:
bitClear(reg17L,3); // Reg 17: manual SPDIF -Clear bit 3
writeSabreLeftReg(0x11,reg17L); // Reg 17: Auto spdif detection OFF
#ifdef DUALMONO
bitClear(reg17R,3); // Reg 17: manual SPDIF -Clear bit 3
writeSabreRightReg(0x11,reg17R); // Reg 17: Auto spdif detection OFF
#endif DUALMONO
writeSabreReg(0x08,0x68); // Reg 8: Enable I2S/DSD input format
spdifIn=false; // Set variable to indicate input format is I2S/DSD mode
Serial.println("I2S/DSD");
break;
//tft.write(127); // Print Arrow to indicate this is input seletion and not signal
}
}
void setAndPrintInput(byte value){
Serial.print("Input:");
setAndPrintInputFormat(settings[input][FORMATVAL]%FORMATCHO); // Setup input format value
setAndPrintFirFilter(settings[input][FIRVAL]%FIRCHO); // Setup FIR filter value
setAndPrintIirFilter(settings[input][IIRVAL]%IIRCHO); // Setup IIR filter value
setAndPrintDPLL(settings[input][DPLLVAL]%DPLLCHO); // Setup the DPLL value
setAndPrintQuantizer(settings[input][QUANVAL]%QUANCHO); // Setup quantizer value
setAndPrintNotch(settings[input][NOTCHVAL]%NOTCHCHO); // Setup notch delay value
setAndPrintDPLLMode(settings[input][PLMVAL]%PLMCHO); // Setup dpll mode value
switch (value){
case 0:
writeSabreReg(0x12,0x01); // Set SPDIF to input #1
Serial.println(no0);
break;
case 1:
writeSabreReg(0x12,0x02); // Set SPDIF to input #2
Serial.print(no1);
break;
case 2:
writeSabreReg(0x12,0x04); // Set SPDIF to input #3
Serial.println(no2);
break;
case 3:
writeSabreReg(0x12,0x08); // Set SPDIF to input #4
Serial.println(no3);
break;
case 4:
writeSabreReg(0x12,0x10); // Set SPDIF to input #5
Serial.println(no4);
break;
case 5:
writeSabreReg(0x12,0x20); // Set SPDIF to input #6
Serial.println(no5);
break;
case 6:
writeSabreReg(0x12,0x40); // Set SPDIF to input #7
Serial.println(no6);
break;
case 7:
writeSabreReg(0x12,0x80); // Set SPDIF to input #8
Serial.println(no7);
break;
}
}
// Array index into parts of big numbers. Each number consists of 9 custom characters
// in a 3x3 matrix. To print a number, you use the array index corresponding to the number
// times 3. For example to print the number 5, you will print bn1[15], bn1[16] and bn1[17]
// for the first row of the large number, and then bn2[15], bn2[16] and bn2[17] and so on.
// 0 1 2 3 4 5 6 7 8 9
char bn1[]={B,2,1, 2,1,A, 2,2,1, 2,2,1, 0,A,B, B,2,2, B,2,2, 2,2,B, B,2,1, B,2,1};
char bn2[]={B,A,B, A,B,A ,0,6,5, A,2,1, 5,6,B, 2,2,1, B,6,7, A,0,5, B,6,B, 5,6,B};
char bn3[]={4,3,B, 3,B,3, B,3,3, 4,3,B, A,A,B, 4,3,B, 4,3,B, A,B,A, 4,3,B, A,A,B};
void startDac1(){ // Set registers not requiring display info
bitSet(reg10,0); // Set bit zero for reg 10: Mute DACs
writeSabreReg(0x0A,reg10); // Mute DACs. Earliest we can mute the DACs to avoid full vol
setSabreVolume(currAttnu); // Reg 0 to Reg 7 Set volume registers with startup volume level
writeSabreReg(0x0D,0x00); // DAC in-phase
writeSabreReg(0x13,0x00); // DACB anti-phase
writeSabreReg(0x25,0x00); // Use built in filter for stage 1 and stage 2
writeSabreReg(0x0E,reg14); // Reg 14: BuffII input map, trueDiff, normal IIR and Fast rolloff
// Reg 14: except BuffII input map setting, the others will be
// redefined.
/*
The code below may provide some mitigation to the white noise during silence
#ifdef USE80MHZ
writeSabreReg(0x10,0x08); // Reg 16: Turn automute loopback -only to mitigate 352.8KHz noise
writeSabreReg(0x09,0x10); // Reg 9: Set automute time 4x less than default (value is in denom.)
#endif USE80MHZ
*/
#ifdef DUALMONO // DAC registers default to stereo. Set to MONO L/R for dual MONO
bitSet(reg17L,0); // Set for MONO left channel. Right ch variable is already set for MONO
writeSabreLeftReg(0x11,reg17L);
writeSabreRightReg(0x11,reg17R);
#endif DUALMONO
#ifdef TPAPHASE
/* The outputs on each side of each MONO board will be in opposite phase. In order to do this
the phase of the odd dacs are out of phase with the even dacs. Further, buffalo is configured
such that (In dual mono mode) the channel on the DAC which is opposite of the selected channel
carries the same analog signal but in anti-phase (odd dacs are the left channel;
even dacs are the right channel)
See http://hifiduino.wordpress.com/sabre32/ for further explaination
*/
writeSabreLeftReg(0x0D,0x22); // MONO LEFT DACx: odd dacs=in-phase; even dacs=anti-phase
// writeSabreLeftReg(0x13,0x00); // MONO LEFT DACBx: all dacs anti-phase with respect to DACx
writeSabreRightReg(0x0D,0x11); // MONO RIGHT DACx: odd dacs=anti-phase; even dacs=in-phase
// writeSabreRightReg(0x13,0x00); // MONO RIGHT DACBx: all dacs anti-phase with respect to DACx
#endif TPAPHASE
}
void startDac2(){
readSettings();
setAndPrintInput(input);
Serial.print("Over/ling:");
Serial.print("On"); // Indicate oversampling is ON (since this is the default)
Serial.print("-");
Serial.print(currAttnu/2); // Print default volume level
Serial.println("dB");
bitClear(reg10,0); // Clear bit zero of reg 10: unmute DACs
writeSabreReg(0x0A,reg10); // Unmute DACs
}
// The following function attempts to "prime" the DPLL by going through all settings of the DPLL
// May help the i2s locking problem???
void primeDpll(){
bitSet(reg10,0); // Set bit zero of reg 10
writeSabreReg(0x0A,reg10); // Mute DACs.
writeSabreReg(0x19,0x02); // Reg 25: Allow all Best settings
for(int i=8;i>0;i--){ // Select each DPLL settings from largest to smallest BW
writeSabreReg(0x19,0x00); // Reg 25: Allow all DPLL settings at 1X
writeSabreReg(11, (125+(i*4))); // Go through all the DPLL settings
delay(400);
//lcd.setCursor(4,2); // To show in the screen that something is going on
Serial.print("<|>");
writeSabreReg(0x19,0x01); // Reg 25: Allow all DPLL settings at 128X
writeSabreReg(11, (161-(i*4))); // Go through all the DPLL settings
delay(400);
//lcd.setCursor(4,2); // To show in the screen that something is going on
Serial.print(">|<");
}
setAndPrintDPLL(settings[input][DPLLVAL]%DPLLCHO); // Back to original setting for dpll
bitClear(reg10,0); // Clear bit zero of reg 10
writeSabreReg(0x0A,reg10); // Unmute DACs
}
/***************************************************************************************************
* Timer Code starts here
***************************************************************************************************/
int incomingByte = 0; // for incoming serial data
#define INTERVAL 1 // Arbitrary time interval in minutes
unsigned long minutes=0; // Minute count 0 to 59
unsigned long totalMinutes=0; // Total minute count 0 to ...
unsigned long hours=0; // Hours count 0 to ...
unsigned long lastInterval=0; // Time in minutes of last interval
void printTime(){ // Prints hours:minutes as xx:xx
if(hours<10)
Serial.print("0");
Serial.print(hours);
Serial.print(":");
if(minutes<10)
Serial.print("0");
Serial.println(minutes);
}
void keepTime(){ // Keeps track of elapsed time
if(millis()>((60000)+(60000*minutes)+(3600000*hours))){
minutes++;
totalMinutes++;
if(minutes==60){ // For every 60 minutes...
minutes=0; // Reset the minutes and...
hours++; // Increase the hours
}
}
}
void printData(){
Serial.print("Print Data");
printTime();
}
/******************* START Print Utilities derived from setAndPrint functions *********************/
void printInputFormat(byte value){
Serial.print("Input:");
switch(value){
case 0:
Serial.println("S/PDIF");
break;
case 1:
Serial.println("I2S/DSD");
break;
}
}
void printNotch(byte value){
Serial.print("Notch:");
switch(value){
case 0:
Serial.println("NON");
break;
case 1:
Serial.println("/04");
break;
case 2:
Serial.println("/08");
break;
case 3:
Serial.println("/16");
break;
case 4:
Serial.println("/32");
break;
case 5:
Serial.println("/64");
break;
}
}
void printQuantizer(byte value){
Serial.print("Qtz:");
switch(value){
case 0: // 6-bit true diff
Serial.println("6bT");
break;
case 1: // 7-bit pseudo diff
Serial.println("7bP");
break;
case 2: // 7-it true diff
Serial.println("7bT");
break;
case 3: // 8-bit pseudo diff
Serial.println("8bP");
break;
case 4: // 8-bit true diff
Serial.println("8bT");
break;
case 5: // 9-bit pseudo diff
Serial.println("9bP");
break;
}
}
void printIirFilter(byte value){
Serial.print("IIR:");
switch(value){
case 0: // | | | | | |0|0| | IIR Bandwidth: Normal (for PCM)
Serial.println("PCM");
break;
case 1: // | | | | | |0|1| | IIR Bandwidth: 50k (for DSD) (D)
Serial.print("50K");
break;
case 2: // | | | | | |1|0| | IIR Bandwidth: 60k (for DSD)
Serial.println("60K");
break;
case 3: // | | | | | |1|1| | IIR Bandwidth: 70k (for DSD)
Serial.println("70K");
break;
}
}
void printFirFilter(byte value){
Serial.print("Filter:");
switch(value){
case 0:
Serial.println("Sharp FIR");
break;
case 1:
Serial.println("Slow FIR");
break;
}
}
void printBypassOSF(){ // This is just a toggle function
Serial.print("Over/ling:");
if(bypassOSF==true){
Serial.print("On");
}
else {
Serial.println("Off");
}
}
void printDPLLMode(byte value){ // Print the DPLL Mode
Serial.print("DPLL Mode:");
switch(value){
case 0:
Serial.println("x128");
break;
case 1:
Serial.println("x1");
break;
case 2:
Serial.println("NOS");
break;
}
}
void printDPLL(byte value){
Serial.print("DPLL B/W: ");
switch(value){
case 0:
Serial.println("Auto");
break;
case 1:
Serial.println("Lowest");
break;
case 2:
Serial.println("Low");
break;
case 3:
Serial.println("Low-Med");
break;
case 4:
Serial.println("Medium");
break;
case 5:
Serial.println("Med-High");
break;
case 6:
Serial.println("High");
break;
case 7:
Serial.println("Highest");
break;
}
}
void printInput(byte value){
Serial.print("Input:");
printInputFormat(settings[input][FORMATVAL]%FORMATCHO); // Setup input format value
printFirFilter(settings[input][FIRVAL]%FIRCHO); // Setup FIR filter value
printIirFilter(settings[input][IIRVAL]%IIRCHO); // Setup IIR filter value
printDPLL(settings[input][DPLLVAL]%DPLLCHO); // Setup the DPLL value
printQuantizer(settings[input][QUANVAL]%QUANCHO); // Setup quantizer value
printNotch(settings[input][NOTCHVAL]%NOTCHCHO); // Setup notch delay value
printDPLLMode(settings[input][PLMVAL]%PLMCHO); // Setup dpll mode value
switch (value){
case 0:
Serial.println(no0);
break;
case 1:
Serial.print(no1);
break;
case 2:
Serial.println(no2);
break;
case 3:
Serial.println(no3);
break;
case 4:
Serial.println(no4);
break;
case 5:
Serial.println(no5);
break;
case 6:
Serial.println(no6);
break;
case 7:
Serial.println(no7);
break;
}
}
/******************* END Print Utilities derived from setAndPrint functions *********************/
/************************ MAIN PROGRAM ************************************************************/
void setup() {
Serial.begin(9600);
Wire.begin(); // Join the I2C bus as a master
startDac1(); // First part of starting the DAC
Serial.println("H I F I D U I N O");
Serial.println("v.B1.0b STEREO");
#ifdef DUALMONO
Serial.println("DUALMONO");
#endif DUALMONO
#ifdef TPAPHASE
Serial.println("DUAL-TPA");
#endif TPAPHASE
Serial.println("(c) HiFiDUINO Jan 06 2012");
Serial.println("(c) DimDim Mar 11 2012");
Serial.println("(c) tm@VR Apr 11 2012");
Serial.println("");
Serial.println("BuffaloCon 0.1");
Serial.println("Accepting User Input");
Serial.println("Press ? key for help");
delay(1000);
startDac2(); // prints all the values in the screen
} // End setup()
// -------------------------------------loop section------------------------------------------
void loop(){
keepTime();
if((lastInterval+INTERVAL)==totalMinutes){
lastInterval=totalMinutes;
Serial.println("#Interval timer ");
printData();
}
// Serial Port Command Controll
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
//say what you got from serial for debugging
//Serial.print("I received: ");
//Serial.println(incomingByte, DEC);
switch (incomingByte){
case 32: // Space Bar, prints input info
printInput(input);
break;
case 43: // + key, volume up
Serial.println("+++");
if (currAttnu>MINATTNU) // Check if not already at minimum attenuation
{
if(dimmed) {
rampUp(); // Disengage dim
dimmed=false;
}
currAttnu-=2; // Decrease attenuation 1 dB (increase volume 1 db)
setSabreVolume(currAttnu); // Write value into registers
Serial.print("-");
Serial.print(currAttnu/2); // Print volume level
Serial.println("dB");
}
break;
case 45: // - key, volume down
Serial.println("---");
if (currAttnu<MAXATTNU) // Check if not already at maximum attenuation
{
if(dimmed) {
rampUp(); // Disengage dim
dimmed=false;
}
currAttnu+=2; // Increase 1 dB attenuation (decrease volume 1 db)
setSabreVolume(currAttnu); // Write value into registers
Serial.print("-");
Serial.print(currAttnu/2); // Print volume level
Serial.println("dB");
}
break;
case 48: // 0 key. This is the soft mute -dim feature
if(dimmed){ // Back to previous volume level 1 db at a time
rampUp(); // Disengage dim
dimmed=false;
}
else {
if(DIM>=currAttnu) { // only DIM if current attenuation is lower
setSabreVolume(DIM); // Dim volume
Serial.print("-");
Serial.print(currAttnu/2); // Print default volume level
Serial.println("dB");
dimmed=true;
}
}
break;
case 49: // 1 key. Select source no. 1
input=0;
input%=ICHO;
setAndPrintInput(input);
break;
case 50: // 2 key. Select source no. 2
input=1;
input%=ICHO;
setAndPrintInput(input);
break;
case 51: // 3 key. Select source no. 3
input=2;
input%=ICHO;
setAndPrintInput(input);
break;
case 52: // 4 key. Select source no. 4
input=3;
input%=ICHO;
setAndPrintInput(input);
break;
case 53: // 5 key. Select source no. 5
input=4;
input%=ICHO;
setAndPrintInput(input);
break;
case 54: // 6 key. Select source no. 6
input=5;
input%=ICHO;
setAndPrintInput(input);
break;
case 55: // 7 key. Select source no. 7
input=6;
input%=ICHO;
setAndPrintInput(input);
break;
case 56: // 8 key. Select source no. 8
input=7;
input%=ICHO;
setAndPrintInput(input);
break;
case 102: // f key. FIR filter selection
settings[input][FIRVAL]++;
setAndPrintFirFilter(settings[input][FIRVAL]%FIRCHO);
break;
case 105: // i key. IIR filter selection
settings[input][IIRVAL]++;
setAndPrintIirFilter(settings[input][IIRVAL]%IIRCHO);
break;
case 113: // q key. Quantizer selection
settings[input][QUANVAL]++;
setAndPrintQuantizer(settings[input][QUANVAL]%QUANCHO);
break;
case 100: // d key. DPLL setting: separate selection for SPDIF and I2S
settings[input][DPLLVAL]++;
setAndPrintDPLL(settings[input][DPLLVAL]%DPLLCHO);
break;
case 110: // n key. Notch selection
if (digitalRead(4) == digitalRead(2)) settings[input][NOTCHVAL]--; // CCW
else settings[input][NOTCHVAL]++;
setAndPrintNotch(settings[input][NOTCHVAL]%NOTCHCHO);
break;
case 112: // p key. DPLL mode selection
if (digitalRead(4) == digitalRead(2)) settings[input][PLMVAL]--; // CCW
else settings[input][PLMVAL]++;
setAndPrintDPLLMode(settings[input][PLMVAL]%PLMCHO);
break;
case 111: // o key. OSF Bypass -Since this is a toggle, we just call the function
setAndPrintBypassOSF();
break;
case 63: // ? key. OSF Bypass -Since this is a toggle, we just call the function
Serial.println("BuffaloCon Help");
Serial.println("<key>:<command>, f:FIR, i:IIR, q:Quantizer, d:DPLL, n:Notch, p:DPLLMode, o:OSF");
Serial.println("keys 1 to 8:select input 1 to 8");
Serial.println("keys + -:volume up/down");
Serial.println("key 0:mute");
break;
}
}
// "Condition" the dpll lock once at startup to see if it helps the I2S locking
if(!primed){
Status=readStatus(); // Read status register
if(Status&B00000001){ // if there is a lock a lock on a signal
primeDpll();
primed=true;
}
}
// Print the sample rate, input and lock (once every "INTERVAL_SAMPLE" time)
if((millis() - displayMillis > INTERVAL_SAMPLE*1000)&&!selectMode) {
displayMillis = millis(); // Saving last time we display sample rate
Status=readStatus(); // Read status register
if(Status&B00000100) SPDIFValid=true; // Determine if valid spdif data
else SPDIFValid=false; // SR calculation depends on I2S or SPDIf
// Update the sample rate display if there is a lock (otherwise, SR=0)
if(Status&B00000001){ // There is a lock in a signal
sr = sampleRate();
Serial.print(sr, DEC);
if(Status&B00001000) { // Determines if DSD
Serial.print("DSD ");}
else { // If not DSD then it is I2S or SPDIF
if(SPDIFValid){ // If valid spdif data, then it is spdif
Serial.print("S/PDIF ");}
else {
Serial.print("I2S "); // Otherwise it is I2S
}}
}
else { // There is no lock we print input selection
Serial.print("No Lock");}
StatusS=readSPDIFStatus(); // Read SPDIF status register
pro_cons = bitRead(StatusS, 0);
if (pro_cons = 1){
Serial.print("Professional");}
else {
Serial.print("Consumer");}
// Heatbeat to show that the software is still running...
if(pulse++%2){
Serial.println("."); // Print a "pulse" to indicate the controller is working
}
else {
Serial.println("_");
}
}
}
Hardware Setup:
PC -> USB -> Arduino
Arduino pins SCLK, SDA, GND -> Buffalo pins SCLK, SDA, GND (i2c header, remove original IC)
Σημείωση
Το arduino όταν είναι συνδεδεμένο με USB, δίνει πρόσβαση σε μια (ιδεατή) σειριακή θύρα Μέσω της οποίας έχουμε αμφίδρομη επικοινωνία.
Θετικά:
Δεν απαιτείται καμία οθόνη πέραν του υπολογιστή σας. ( μια καλή LCD οθόνη μη ξεχνάμε ότι κάνει ~$40)
Πρόσβαση σε όλες τις δυνατότητες προγραμματισμού του ESS Sabre32.
Ένα καλώδιο usb για τροφοδοσία του arduino και αμφίδρομη επικοινωνία μέσω serial.
Το βουβάλι προσωπικά το έχω για ‛κάρτα ήχου’ με το PC πάντα ανοιχτό σα πηγή. Όποτε με βολεύει να έχω όλα τα controls εκεί διαθέσιμα. Κάτι σαν το interface που δίνουν οι επαγγελματικές κάρτες ήχου, με ενδείξεις για όλες τις λειτουργίες και την πραγματική κατάσταση.
Πολύ απλό Keyboard Interface:
<key>:<command>
f:FIR, i : IIR, q : Quantizer, d : DPLL, n : Notch, p : DPLLMode, o : OSF
keys 1 to 8:select input 1 to 8
keys + -:volume up/down
Screen Capture:
Code:
H I F I D U I N O
v.B1.0b STEREO
(c) HiFiDUINO Jan 06 2012
(c) DimDim Mar 11 2012
(c) tm@VR Apr 11 2012
BuffaloCon 0.1
Accepting User Input
Press ? key for help
Input:Input:I2S/DSD
Filter:Sharp FIR
IIR:PCM
DPLL B/W: Lowest
Qtz:8bT
Notch:/04
DPLL Mode:x128
Over/ling:On-2dB
<|>>|<<|>>|<<|>>|<<|>>|<<|>>|<<|>>|<<|>>|<<|>>|<DPLL B/W: Lowest
No LockProfessional_
47999I2S Professional.
47999I2S Professional_
47999I2S Professional.
47999I2S Professional_
BuffaloCon Help
<key>:<command>, f:FIR, i:IIR, q:Quantizer, d:DPLL, n:Notch, p:DPLLMode, o:OSF
keys 1 to 8:select input 1 to 8
keys + -:volume up/down
key 0:mute
47999I2S Professional.
47999I2S Professional_
47999I2S Professional.
Filter:Slow FIR
47999I2S Professional_
Input:Input:I2S/DSD
Filter:Slow FIR
IIR:PCM
DPLL B/W: Lowest
Qtz:8bT
Notch:/04
DPLL Mode:x128
47999I2S Professional.
+++
-1dB
47999I2S Professional_
Input:Input:I2S/DSD
Filter:Slow FIR
IIR:PCM
DPLL B/W: Lowest
Qtz:8bT
Notch:/04
DPLL Mode:x128
47999I2S Professional.
+++
-0dB
Input:Input:I2S/DSD
Filter:Slow FIR
IIR:PCM
DPLL B/W: Lowest
Qtz:8bT
Notch:/04
DPLL Mode:x128
47999I2S Professional_
47999I2S Professional.
47999I2S Professional_
47999I2S Professional.
47999I2S Professional_