1

Тема: CS8416 + WM8740

http://forum.rcl-radio.ru/uploads/images/2020/11/f2faf7cf7f5c16bb57b1180c10db8e88.gif

http://forum.rcl-radio.ru/uploads/images/2020/11/666199386da3f0c876aefebf56d2451f.png

http://forum.rcl-radio.ru/uploads/images/2020/11/81575965e8ef2ab009c4bed6df5311b9.png

http://forum.rcl-radio.ru/uploads/images/2020/11/e00f036e96149af2b310a17810188382.png

http://forum.rcl-radio.ru/uploads/images/2022/03/5c9fe6234a4060a4d544a60d5ef7f227.png


#define CS   2  // ML WM8740
#define CLK  3  // MC WM8740
#define DATA 4  // MD WM8740

#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
      byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
      byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
      byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
      byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
      byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
      int a[3],vol,vol_d,menu,in,dem,form;
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
      unsigned long times,times1,oldPosition  = -999,newPosition;
      bool w,w1,www=1,mute;
      byte rol,dac_i2s,dac_iw,dem_res,for_dac,for_res,err,err_old;

void setup(){
   Wire.begin();
   Serial.begin(9600);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
   lcd.init();lcd.backlight();
   lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   pinMode(10,INPUT);   // SW энкодер
   pinMode(11,INPUT_PULLUP); // кнопка MUTE      
   pinMode(CS,OUTPUT);  // ML WM8740
   pinMode(CLK,OUTPUT); // MC WM8740
   pinMode(DATA,OUTPUT);// MD WM8740
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении 
  vol = EEPROM.read(0);in = EEPROM.read(1);dem_res = EEPROM.read(3);for_dac = EEPROM.read(4);for_res = EEPROM.read(5);
  dac_i2s = EEPROM.read(6);dac_iw = EEPROM.read(7);rol = EEPROM.read(8);
   lcd.setCursor(0,0);lcd.print(" CS8416  WM8740 ");
   lcd.setCursor(0,1);lcd.print(" 24 bit  192kHz ");
  // Write WM8740 SPI
  wireWrite(0b000100000000);//reg0
  wireWrite(0b001100000000);//reg1
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite(0b110000000000);//reg4
// Write 8416 I2C
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(2000);lcd.clear();
  // Write WM8740 SPI
  wireWrite(0b000100000000 + vol);//reg0
  wireWrite(0b001100000000 + vol);//reg1
  }

void loop(){ 
 /// MENU //////////////////////////////
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;};delay(200);lcd.clear();times=millis();w=1;w1=1;www=1;}
 /// MUTE /////////////////////////////
 if(digitalRead(11)==LOW && mute==0){mute=1; wireWrite(0b010000000001 + (dac_iw << 3));delay(300);www=1;} 
 if(digitalRead(11)==LOW && mute==1){mute=0; wireWrite(0b010000000000 + (dac_iw << 3));delay(300);www=1;} 
  
   if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     vol=vol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(vol<155){vol=155;}if(vol>255){vol=255;}
    wireWrite(0b000100000000 + vol);//reg0
    wireWrite(0b001100000000 + vol);//reg1
    Serial.println(vol);// vol = 155...255 step 0.5 dB
  }
  if(www==1||w==1){www=0;w=0;
      if(mute==1){         lcd.setCursor(0,0);lcd.print("MUTE    ");}
      if(err==0&&mute==0){ lcd.setCursor(0,0);lcd.print("VOLUME  ");}
      if(err==22&&mute==0){lcd.setCursor(0,0);lcd.print("ERROR   ");}
      if(err==8&&mute==0){ lcd.setCursor(0,0);lcd.print("NO SOUND");}
 
      lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in);
     vol_d=vol-156;a[0]=vol_d/10;a[1]=vol_d%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 //////// INPUT ////////////////////////////////////  
  if(menu==1){
    if (newPosition != oldPosition){oldPosition = newPosition;
     in=in-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(in<0){in=0;}if(in>7){in=7;}
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();}
  delay(10);
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("INPUT SELECTOR");  
  lcd.setCursor(0,1);lcd.print("COAXIAL "); lcd.print(in);lcd.print(" ");
  }}
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// DE-EMPHASIS //////////////////////////////////
  if(menu==2){
    if (newPosition != oldPosition){oldPosition = newPosition;
     dem=dem-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(dem<0){dem=0;}if(dem>3){dem=3;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("DE-EMPHASIS SEL");  
  lcd.setCursor(0,1);
  switch(dem){
  case 0: lcd.print("No De-emphasis");dem_res=0;break;
  case 1: lcd.print("44.1 kHz      ");dem_res=2;break;
  case 2: lcd.print("48.0 kHz      ");dem_res=3;break;
  case 3: lcd.print("32.0 kHz      ");dem_res=1;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   ///  FILTER ROLL-OFF //////////////////////////////////
  if(menu==3){
    if (newPosition != oldPosition){oldPosition = newPosition;
     rol=rol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(rol<0){rol=0;}if(rol>1){rol=1;}
      
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("ROLL-OFF SELECT ");  
  lcd.setCursor(0,1);
  switch(rol){
  case 0: lcd.print("Sharp");break;
  case 1: lcd.print("Slow ");break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// Serial Format Select //////////////////////////////////
  if(menu==4){
    if (newPosition != oldPosition){oldPosition = newPosition;
     form=form-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
     if(form<0){form=0;}if(form>2){form=2;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("FORMAT SELECT");  
  lcd.setCursor(0,1);
  switch(form){
  case 0: lcd.print("L-Just 24 bit");dac_i2s=0;dac_iw=3;for_res=0;break;
  case 1: lcd.print("I2S    24 bit");dac_i2s=1;dac_iw=1;for_res=5;break;
  case 2: lcd.print("R-Just 24 bit");dac_i2s=0;dac_iw=2;for_res=8;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// read registr error 
  if(millis()-times1>1000){times1=millis();err = wireRead(0x10,0x0C);delay(10);}
  if(err!=err_old){err_old = err;www=1;}       
  /// EEPROM write
  if(millis()-times>10000 && w1==1){w1=0;EEPROM.update(0,vol);EEPROM.update(1,in);
  EEPROM.update(3,dem_res);EEPROM.update(4,for_dac);EEPROM.update(5,for_res);
  EEPROM.update(6,dac_i2s);EEPROM.update(7,dac_iw);EEPROM.update(8,rol);
  menu=0;www=1;if(menu!=0){lcd.clear();}}
  delay(100);
  }// loop  

void wireWrite(int data){        // SPI
  digitalWrite(CLK,HIGH);digitalWrite(CS,HIGH);delay(1);
     for(int i = 15; i >= 0; i--){
        digitalWrite(CLK,LOW);
        digitalWrite(DATA, (data >> i) & 0x01);delay(1);
        digitalWrite(CLK,HIGH);delay(1);}
  digitalWrite(CS,LOW);delay(1);digitalWrite(CS,HIGH);
  }

byte wireRead(int addr, int reg){ // I2C
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

2

Re: CS8416 + WM8740

Добавлен баланс +/- 5 дБ (шаг регулировки 0,5 дБ)

http://forum.rcl-radio.ru/uploads/images/2020/11/cd3607005cf79ebf3bbfd8da92035c08.png
http://forum.rcl-radio.ru/uploads/images/2020/11/95c12cc331d90318eb72c1023c641304.png
http://forum.rcl-radio.ru/uploads/images/2020/11/28b02aef70f5497e5d6f865100d30955.png

#define CS   2  // ML WM8740
#define CLK  3  // MC WM8740
#define DATA 4  // MD WM8740

#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
      byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
      byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
      byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
      byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
      byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
      int a[3],vol,vol_d,menu,in,dem,form,ball,rol;
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
      unsigned long times,times1,oldPosition  = -999,newPosition;
      bool w,w1,www=1,mute;
      byte dac_i2s,dac_iw,dem_res,for_dac,for_res,err,err_old;

void setup(){
   Wire.begin();
   Serial.begin(9600);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
   lcd.init();lcd.backlight();
   lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   pinMode(10,INPUT);   // SW энкодер
   pinMode(11,INPUT_PULLUP); // кнопка MUTE      
   pinMode(CS,OUTPUT);  // ML WM8740
   pinMode(CLK,OUTPUT); // MC WM8740
   pinMode(DATA,OUTPUT);// MD WM8740
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении 
  vol = EEPROM.read(0);in = EEPROM.read(1);dem_res = EEPROM.read(3);for_dac = EEPROM.read(4);for_res = EEPROM.read(5);
  dac_i2s = EEPROM.read(6);dac_iw = EEPROM.read(7);rol = EEPROM.read(8);ball = EEPROM.read(9)-10;
   lcd.setCursor(0,0);lcd.print(" CS8416  WM8740 ");
   lcd.setCursor(0,1);lcd.print(" 24 bit  192kHz ");
  // Write WM8740 SPI
  wireWrite(0b000100000000);//reg0
  wireWrite(0b001100000000);//reg1
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite(0b110000000000);//reg4
// Write 8416 I2C
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(200);lcd.clear();
  // Write WM8740 SPI
   wireWrite(0b000100000000 + vol+10 + ball);//reg0
   wireWrite(0b001100000000 + vol+10 - ball);//reg1
  }

void loop(){ 
 /// MENU //////////////////////////////
  if(digitalRead(10)==LOW){menu++;if(menu>5){menu=0;};delay(200);lcd.clear();times=millis();w=1;w1=1;www=1;}
 /// MUTE /////////////////////////////
 if(digitalRead(11)==LOW && mute==0){mute=1; wireWrite(0b010000000001 + (dac_iw << 3));delay(300);www=1;} 
 if(digitalRead(11)==LOW && mute==1){mute=0; wireWrite(0b010000000000 + (dac_iw << 3));delay(300);www=1;} 

 /// VOLUME /////////////////////////////////// 
   if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     vol=vol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(vol<145){vol=145;}if(vol>245){vol=245;}
    wireWrite(0b000100000000 + vol+10 + ball);//reg0
    wireWrite(0b001100000000 + vol+10 - ball);//reg1
    Serial.println(vol);// vol = 145...245 step 0.5 dB + 10 balance
  }
  if(www==1||w==1){www=0;w=0;
      if(mute==1){         lcd.setCursor(0,0);lcd.print("MUTE    ");}
      if(err==0&&mute==0){ lcd.setCursor(0,0);lcd.print("VOLUME  ");}
      if(err==22&&mute==0){lcd.setCursor(0,0);lcd.print("ERROR   ");}
      if(err==8&&mute==0){ lcd.setCursor(0,0);lcd.print("NO SOUND");}
 
      lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in);
     vol_d=vol-156;a[0]=vol_d/10;a[1]=vol_d%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 /// BALANCE ////////////////////////////
   if(menu==1){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     ball=ball-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(ball<-10){ball=-10;}if(ball>10){ball=10;}
    wireWrite(0b000100000000 + vol+10 + ball);//reg0
    wireWrite(0b001100000000 + vol+10 - ball);//reg1
    Serial.println(ball);
  }
  if(www==1||w==1){www=0;w=0;
      if(ball<0){lcd.setCursor(8,1);lcd.write((uint8_t)0);
                 lcd.setCursor(0,1);lcd.print("L > R");}                
      if(ball>0){lcd.setCursor(8,1);lcd.print(" ");
                 lcd.setCursor(0,1);lcd.print("L < R");}
     if(ball==0){lcd.setCursor(8,1);lcd.print(" ");
                 lcd.setCursor(0,1);lcd.print("L = R");}
      lcd.setCursor(0,0);lcd.print("BALANCE ");

      a[0]=abs(ball)/10;a[1]=abs(ball)%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}

 //////// INPUT ////////////////////////////////////  
  if(menu==2){
    if (newPosition != oldPosition){oldPosition = newPosition;
     in=in-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(in<0){in=0;}if(in>7){in=7;}
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();}
  delay(10);
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("INPUT SELECTOR");  
  lcd.setCursor(0,1);lcd.print("COAXIAL "); lcd.print(in);lcd.print(" ");
  }}
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// DE-EMPHASIS //////////////////////////////////
  if(menu==3){
    if (newPosition != oldPosition){oldPosition = newPosition;
     dem=dem-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(dem<0){dem=0;}if(dem>3){dem=3;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("DE-EMPHASIS SEL");  
  lcd.setCursor(0,1);
  switch(dem){
  case 0: lcd.print("No De-emphasis");dem_res=0;break;
  case 1: lcd.print("44.1 kHz      ");dem_res=2;break;
  case 2: lcd.print("48.0 kHz      ");dem_res=3;break;
  case 3: lcd.print("32.0 kHz      ");dem_res=1;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   ///  FILTER ROLL-OFF //////////////////////////////////
  if(menu==4){
    if (newPosition != oldPosition){oldPosition = newPosition;
     rol=rol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(rol<0){rol=1;}if(rol>1){rol=0;}
      
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("ROLL-OFF SELECT ");  
  lcd.setCursor(0,1);
  switch(rol){
  case 0: lcd.print("Sharp");break;
  case 1: lcd.print("Slow ");break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// Serial Format Select //////////////////////////////////
  if(menu==5){
    if (newPosition != oldPosition){oldPosition = newPosition;
     form=form-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
     if(form<0){form=0;}if(form>2){form=2;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("FORMAT SELECT");  
  lcd.setCursor(0,1);
  switch(form){
  case 0: lcd.print("L-Just 24 bit");dac_i2s=0;dac_iw=3;for_res=0;break;
  case 1: lcd.print("I2S    24 bit");dac_i2s=1;dac_iw=1;for_res=5;break;
  case 2: lcd.print("R-Just 24 bit");dac_i2s=0;dac_iw=2;for_res=8;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// read registr error 
  if(millis()-times1>1000){times1=millis();err = wireRead(0x10,0x0C);delay(10);}
  if(err!=err_old){err_old = err;www=1;}       
  /// EEPROM write
  if(millis()-times>10000 && w1==1){w1=0;EEPROM.update(0,vol);EEPROM.update(1,in);
  EEPROM.update(3,dem_res);EEPROM.update(4,for_dac);EEPROM.update(5,for_res);
  EEPROM.update(6,dac_i2s);EEPROM.update(7,dac_iw);EEPROM.update(8,rol);EEPROM.update(9,ball+10);
  www=1;if(menu!=0){lcd.clear();}menu=0;}
  delay(100);
  }// loop  

void wireWrite(int data){        // SPI
  digitalWrite(CLK,HIGH);digitalWrite(CS,HIGH);delay(1);
     for(int i = 15; i >= 0; i--){
        digitalWrite(CLK,LOW);
        digitalWrite(DATA, (data >> i) & 0x01);delay(1);
        digitalWrite(CLK,HIGH);delay(1);}
  digitalWrite(CS,LOW);delay(1);digitalWrite(CS,HIGH);
  }

byte wireRead(int addr, int reg){ // I2C
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

3

Re: CS8416 + WM8740

Добавлен список поддерживаемых входных форматов:

  • L-Just 24 bit

  • I2S    24 bit

  • R-Just 24 bit

  • L-Just 20 bit

  • I2S    20 bit

  • I2S    16 bit

#define CS   2  // ML WM8740
#define CLK  3  // MC WM8740
#define DATA 4  // MD WM8740

#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
      byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
      byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
      byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
      byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
      byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
      int a[3],vol,vol_d,menu,in,dem,form,ball,rol;
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
      unsigned long times,times1,oldPosition  = -999,newPosition;
      bool w,w1,www=1,mute;
      byte dac_i2s,dac_iw,dem_res,for_dac,for_res,err,err_old;

void setup(){
   Wire.begin();
   Serial.begin(9600);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
   lcd.init();lcd.backlight();
   lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   pinMode(10,INPUT);   // SW энкодер
   pinMode(11,INPUT_PULLUP); // кнопка MUTE      
   pinMode(CS,OUTPUT);  // ML WM8740
   pinMode(CLK,OUTPUT); // MC WM8740
   pinMode(DATA,OUTPUT);// MD WM8740
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении 
  vol = EEPROM.read(0);in = EEPROM.read(1);dem_res = EEPROM.read(3);for_dac = EEPROM.read(4);for_res = EEPROM.read(5);
  dac_i2s = EEPROM.read(6);dac_iw = EEPROM.read(7);rol = EEPROM.read(8);ball = EEPROM.read(9)-10;
   lcd.setCursor(0,0);lcd.print(" CS8416  WM8740 ");
   lcd.setCursor(0,1);lcd.print(" 24 bit  192kHz ");
  // Write WM8740 SPI
  wireWrite(0b000100000000);//reg0
  wireWrite(0b001100000000);//reg1
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite(0b110000000000);//reg4
// Write 8416 I2C
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(200);lcd.clear();
  // Write WM8740 SPI
   wireWrite(0b000100000000 + vol+10 + ball);//reg0
   wireWrite(0b001100000000 + vol+10 - ball);//reg1
  }

void loop(){ 
 /// MENU //////////////////////////////
  if(digitalRead(10)==LOW){menu++;if(menu>5){menu=0;};delay(200);lcd.clear();times=millis();w=1;w1=1;www=1;}
 /// MUTE /////////////////////////////
 if(digitalRead(11)==LOW && mute==0){mute=1; wireWrite(0b010000000001 + (dac_iw << 3));delay(300);www=1;} 
 if(digitalRead(11)==LOW && mute==1){mute=0; wireWrite(0b010000000000 + (dac_iw << 3));delay(300);www=1;} 

 /// VOLUME /////////////////////////////////// 
   if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     vol=vol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(vol<145){vol=145;}if(vol>245){vol=245;}
    wireWrite(0b000100000000 + vol+10 + ball);//reg0
    wireWrite(0b001100000000 + vol+10 - ball);//reg1
    Serial.println(vol);// vol = 145...245 step 0.5 dB + 10 balance
  }
  if(www==1||w==1){www=0;w=0;
      if(mute==1){         lcd.setCursor(0,0);lcd.print("MUTE    ");}
      if(err==0&&mute==0){ lcd.setCursor(0,0);lcd.print("VOLUME  ");}
      if(err==22&&mute==0){lcd.setCursor(0,0);lcd.print("ERROR   ");}
      if(err==8&&mute==0){ lcd.setCursor(0,0);lcd.print("NO SOUND");}
 
      lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in);
     vol_d=vol-156;a[0]=vol_d/10;a[1]=vol_d%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 /// BALANCE ////////////////////////////
   if(menu==1){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     ball=ball-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(ball<-10){ball=-10;}if(ball>10){ball=10;}
    wireWrite(0b000100000000 + vol+10 + ball);//reg0
    wireWrite(0b001100000000 + vol+10 - ball);//reg1
    Serial.println(ball);
  }
  if(www==1||w==1){www=0;w=0;
      if(ball<0){lcd.setCursor(8,1);lcd.write((uint8_t)0);
                 lcd.setCursor(0,1);lcd.print("L > R");}                
      if(ball>0){lcd.setCursor(8,1);lcd.print(" ");
                 lcd.setCursor(0,1);lcd.print("L < R");}
     if(ball==0){lcd.setCursor(8,1);lcd.print(" ");
                 lcd.setCursor(0,1);lcd.print("L = R");}
      lcd.setCursor(0,0);lcd.print("BALANCE ");

      a[0]=abs(ball)/10;a[1]=abs(ball)%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}

 //////// INPUT ////////////////////////////////////  
  if(menu==2){
    if (newPosition != oldPosition){oldPosition = newPosition;
     in=in-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(in<0){in=0;}if(in>7){in=7;}
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();}
  delay(10);
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("INPUT SELECTOR");  
  lcd.setCursor(0,1);lcd.print("COAXIAL "); lcd.print(in);lcd.print(" ");
  }}
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// DE-EMPHASIS //////////////////////////////////
  if(menu==3){
    if (newPosition != oldPosition){oldPosition = newPosition;
     dem=dem-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(dem<0){dem=0;}if(dem>3){dem=3;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("DE-EMPHASIS SEL");  
  lcd.setCursor(0,1);
  switch(dem){
  case 0: lcd.print("No De-emphasis");dem_res=0;break;
  case 1: lcd.print("44.1 kHz      ");dem_res=2;break;
  case 2: lcd.print("48.0 kHz      ");dem_res=3;break;
  case 3: lcd.print("32.0 kHz      ");dem_res=1;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   ///  FILTER ROLL-OFF //////////////////////////////////
  if(menu==4){
    if (newPosition != oldPosition){oldPosition = newPosition;
     rol=rol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(rol<0){rol=1;}if(rol>1){rol=0;}
      
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("ROLL-OFF SELECT ");  
  lcd.setCursor(0,1);
  switch(rol){
  case 0: lcd.print("Sharp");break;
  case 1: lcd.print("Slow ");break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// Serial Format Select //////////////////////////////////
  if(menu==5){
    if (newPosition != oldPosition){oldPosition = newPosition;
     form=form-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
     if(form<0){form=0;}if(form>5){form=5;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  wireWrite(0b000100000000);//reg0
  wireWrite(0b001100000000);//reg1
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite(0b000100000000 + vol+10 + ball);//reg0
  wireWrite(0b001100000000 + vol+10 - ball);//reg1
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("FORMAT SELECT");  
  lcd.setCursor(0,1);
  switch(form){
  case 0: lcd.print("L-Just 24 bit");dac_i2s=0;dac_iw=3;for_res=0;break;
  case 1: lcd.print("I2S    24 bit");dac_i2s=1;dac_iw=1;for_res=5;break;
  case 2: lcd.print("R-Just 24 bit");dac_i2s=0;dac_iw=2;for_res=8;break;
  case 3: lcd.print("L-Just 20 bit");dac_i2s=1;dac_iw=3;for_res=0;break; 
  case 4: lcd.print("I2S    20 bit");dac_i2s=1;dac_iw=2;for_res=5;break; 
  case 5: lcd.print("I2S    16 bit");dac_i2s=1;dac_iw=0;for_res=5;break;
  
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// read registr error 
  if(millis()-times1>1000){times1=millis();err = wireRead(0x10,0x0C);delay(10);}
  if(err!=err_old){err_old = err;www=1;}       
  /// EEPROM write
  if(millis()-times>10000 && w1==1){w1=0;EEPROM.update(0,vol);EEPROM.update(1,in);
  EEPROM.update(3,dem_res);EEPROM.update(4,for_dac);EEPROM.update(5,for_res);
  EEPROM.update(6,dac_i2s);EEPROM.update(7,dac_iw);EEPROM.update(8,rol);EEPROM.update(9,ball+10);
  www=1;if(menu!=0){lcd.clear();}menu=0;}
  delay(100);
  }// loop  

void wireWrite(int data){        // SPI
  digitalWrite(CLK,HIGH);digitalWrite(CS,HIGH);delay(1);
     for(int i = 15; i >= 0; i--){
        digitalWrite(CLK,LOW);
        digitalWrite(DATA, (data >> i) & 0x01);delay(1);
        digitalWrite(CLK,HIGH);delay(1);}
  digitalWrite(CS,LOW);delay(1);digitalWrite(CS,HIGH);
  }

byte wireRead(int addr, int reg){ // I2C
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

4

Re: CS8416 + WM8740

Коррекция ошибок в CS8416:

HOLD[1:0] – Determine how received audio sample is affected when a receive error occurs
Default = ‘00’
00 – hold last audio sample.
01 – replace the current audio sample with all zeros (mute).
10- do not change the received audio sample.
11 - reserved

http://forum.rcl-radio.ru/uploads/images/2020/11/197a39d33b6934e860cbe87faf0e9faf.png

Установлены биты HOLD  HOLD[1:0] = 01

#define CS   2  // ML WM8740
#define CLK  3  // MC WM8740
#define DATA 4  // MD WM8740

#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
      byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
      byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
      byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
      byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
      byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
      int a[3],vol,vol_d,menu,in,dem,form,ball,rol;
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
      unsigned long times,times1,oldPosition  = -999,newPosition;
      bool w,w1,www=1,mute;
      byte dac_i2s,dac_iw,dem_res,for_dac,for_res,err,err_old;

void setup(){
   Wire.begin();
   Serial.begin(9600);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
   lcd.init();lcd.backlight();
   lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   pinMode(10,INPUT);   // SW энкодер
   pinMode(11,INPUT_PULLUP); // кнопка MUTE      
   pinMode(CS,OUTPUT);  // ML WM8740
   pinMode(CLK,OUTPUT); // MC WM8740
   pinMode(DATA,OUTPUT);// MD WM8740
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении 
  vol = EEPROM.read(0);in = EEPROM.read(1);dem_res = EEPROM.read(3);for_dac = EEPROM.read(4);for_res = EEPROM.read(5);
  dac_i2s = EEPROM.read(6);dac_iw = EEPROM.read(7);rol = EEPROM.read(8);ball = EEPROM.read(9)-10;
   lcd.setCursor(0,0);lcd.print(" CS8416  WM8740 ");
   lcd.setCursor(0,1);lcd.print(" 24 bit  192kHz ");
  // Write WM8740 SPI
  wireWrite(0b000100000000);//reg0
  wireWrite(0b001100000000);//reg1
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite(0b110000000000);//reg4
// Write 8416 I2C
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000110);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(200);lcd.clear();
  // Write WM8740 SPI
   wireWrite(0b000100000000 + vol+10 + ball);//reg0
   wireWrite(0b001100000000 + vol+10 - ball);//reg1
  }

void loop(){ 
 /// MENU //////////////////////////////
  if(digitalRead(10)==LOW){menu++;if(menu>5){menu=0;};delay(200);lcd.clear();times=millis();w=1;w1=1;www=1;}
 /// MUTE /////////////////////////////
 if(digitalRead(11)==LOW && mute==0){mute=1; wireWrite(0b010000000001 + (dac_iw << 3));delay(300);www=1;} 
 if(digitalRead(11)==LOW && mute==1){mute=0; wireWrite(0b010000000000 + (dac_iw << 3));delay(300);www=1;} 

 /// VOLUME /////////////////////////////////// 
   if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     vol=vol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(vol<145){vol=145;}if(vol>245){vol=245;}
    wireWrite(0b000100000000 + vol+10 + ball);//reg0
    wireWrite(0b001100000000 + vol+10 - ball);//reg1
    Serial.println(vol);// vol = 145...245 step 0.5 dB + 10 balance
  }
  if(www==1||w==1){www=0;w=0;
      if(mute==1){         lcd.setCursor(0,0);lcd.print("MUTE    ");}
      if(err==0&&mute==0){ lcd.setCursor(0,0);lcd.print("VOLUME  ");}
      if(err==22&&mute==0){lcd.setCursor(0,0);lcd.print("ERROR   ");}
      if(err==8&&mute==0){ lcd.setCursor(0,0);lcd.print("NO SOUND");}
 
      lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in);
     vol_d=vol-156;a[0]=vol_d/10;a[1]=vol_d%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 /// BALANCE ////////////////////////////
   if(menu==1){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     ball=ball-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(ball<-10){ball=-10;}if(ball>10){ball=10;}
    wireWrite(0b000100000000 + vol+10 + ball);//reg0
    wireWrite(0b001100000000 + vol+10 - ball);//reg1
    Serial.println(ball);
  }
  if(www==1||w==1){www=0;w=0;
      if(ball<0){lcd.setCursor(8,1);lcd.write((uint8_t)0);
                 lcd.setCursor(0,1);lcd.print("L > R");}                
      if(ball>0){lcd.setCursor(8,1);lcd.print(" ");
                 lcd.setCursor(0,1);lcd.print("L < R");}
     if(ball==0){lcd.setCursor(8,1);lcd.print(" ");
                 lcd.setCursor(0,1);lcd.print("L = R");}
      lcd.setCursor(0,0);lcd.print("BALANCE ");

      a[0]=abs(ball)/10;a[1]=abs(ball)%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}

 //////// INPUT ////////////////////////////////////  
  if(menu==2){
    if (newPosition != oldPosition){oldPosition = newPosition;
     in=in-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(in<0){in=0;}if(in>7){in=7;}
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000110);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();}
  delay(10);
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("INPUT SELECTOR");  
  lcd.setCursor(0,1);lcd.print("COAXIAL "); lcd.print(in);lcd.print(" ");
  }}
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// DE-EMPHASIS //////////////////////////////////
  if(menu==3){
    if (newPosition != oldPosition){oldPosition = newPosition;
     dem=dem-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(dem<0){dem=0;}if(dem>3){dem=3;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000110);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("DE-EMPHASIS SEL");  
  lcd.setCursor(0,1);
  switch(dem){
  case 0: lcd.print("No De-emphasis");dem_res=0;break;
  case 1: lcd.print("44.1 kHz      ");dem_res=2;break;
  case 2: lcd.print("48.0 kHz      ");dem_res=3;break;
  case 3: lcd.print("32.0 kHz      ");dem_res=1;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   ///  FILTER ROLL-OFF //////////////////////////////////
  if(menu==4){
    if (newPosition != oldPosition){oldPosition = newPosition;
     rol=rol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(rol<0){rol=1;}if(rol>1){rol=0;}
      
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("ROLL-OFF SELECT ");  
  lcd.setCursor(0,1);
  switch(rol){
  case 0: lcd.print("Sharp");break;
  case 1: lcd.print("Slow ");break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////

   /// Serial Format Select //////////////////////////////////
  if(menu==5){
    if (newPosition != oldPosition){oldPosition = newPosition;
     form=form-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
     if(form<0){form=0;}if(form>5){form=5;}
  
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000110);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  wireWrite(0b000100000000);//reg0
  wireWrite(0b001100000000);//reg1
  wireWrite(0b010000000000 + (dac_iw << 3));//reg2
  wireWrite(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite(0b000100000000 + vol+10 + ball);//reg0
  wireWrite(0b001100000000 + vol+10 - ball);//reg1
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("FORMAT SELECT");  
  lcd.setCursor(0,1);
  switch(form){
  case 0: lcd.print("L-Just 24 bit");dac_i2s=0;dac_iw=3;for_res=0;break;
  case 1: lcd.print("I2S    24 bit");dac_i2s=1;dac_iw=1;for_res=5;break;
  case 2: lcd.print("R-Just 24 bit");dac_i2s=0;dac_iw=2;for_res=8;break;
  case 3: lcd.print("L-Just 20 bit");dac_i2s=1;dac_iw=3;for_res=0;break; 
  case 4: lcd.print("I2S    20 bit");dac_i2s=1;dac_iw=2;for_res=5;break; 
  case 5: lcd.print("I2S    16 bit");dac_i2s=1;dac_iw=0;for_res=5;break;
  
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// read registr error 
  if(millis()-times1>1000){times1=millis();err = wireRead(0x10,0x0C);delay(10);}
  if(err!=err_old){err_old = err;www=1;}       
  /// EEPROM write
  if(millis()-times>10000 && w1==1){w1=0;EEPROM.update(0,vol);EEPROM.update(1,in);
  EEPROM.update(3,dem_res);EEPROM.update(4,for_dac);EEPROM.update(5,for_res);
  EEPROM.update(6,dac_i2s);EEPROM.update(7,dac_iw);EEPROM.update(8,rol);EEPROM.update(9,ball+10);
  www=1;if(menu!=0){lcd.clear();}menu=0;}
  delay(100);
  }// loop  

void wireWrite(int data){        // SPI
  digitalWrite(CLK,HIGH);digitalWrite(CS,HIGH);delay(1);
     for(int i = 15; i >= 0; i--){
        digitalWrite(CLK,LOW);
        digitalWrite(DATA, (data >> i) & 0x01);delay(1);
        digitalWrite(CLK,HIGH);delay(1);}
  digitalWrite(CS,LOW);delay(1);digitalWrite(CS,HIGH);
  }

byte wireRead(int addr, int reg){ // I2C
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

5

Re: CS8416 + WM8740

Здравствуйте! Скажите пожалуйста, на Вашей схеме вывод 15 AVDD WM8740 посажен на землю. Это правильно? Не опечатка? Согласно даташиту там +5В.

6

Re: CS8416 + WM8740

Да Вы правы, это опечатка. Я внес исправления.

7

Re: CS8416 + WM8740

Спасибо!

8

Re: CS8416 + WM8740

Здравствуйте! Я собрал ЦАП. Все работает отлично, единственное, если не пользоваться энкодером некоторое время, устройство перестает реагировать на него.  После перезапуска, все опять работает какое-то время, но потом энкодер опять зависает и не реагирует ни на какие действия. На экране остаются последние показания уровня и коммутатора. Что может быть? Может это программная ошибка где-то? Проверьте пожалуйста. Прошивка самая последняя с этого форума 2020-11-24.

9

Re: CS8416 + WM8740

Кнопка INPUT и MUTE тоже перестают работать?

10

Re: CS8416 + WM8740

MUTE я не подключал, а INPUT это какая? Если на энкодере, то тоже не работает.

11

Re: CS8416 + WM8740

Тут дело не в энкодере, зависает контроллер, скорее всего помеха по питанию, попробуйте установить конденсаторы на +5V Arduino 0.1 мкФ и электролитический на 100 мкФ.

12

Re: CS8416 + WM8740

Хорошо, попробую. Завтра отпишусь по результату. Правда я не на "Ардуино" делал, а разработал свою плату и на ней распаял контроллер А328 с необходимой обвязкой.

13

Re: CS8416 + WM8740

Здравствуйте! Не помогло. Выявилась еще одна странность. При лёгком прикосновении к корпусу 8416 регулировки также зависают. Все ножки пропаяны, так что проблема не в этом.

14

Re: CS8416 + WM8740

на пин reset контроллера подано +5 В через 10 К?

15

Re: CS8416 + WM8740

Похоже на зависание шины i2c, проверьте подтягивающие резисторы.

Уменьшите частоту шины до 50000 кгц :
Wire.setClock(50000L);
вызываться после Wire.begin();

16

Re: CS8416 + WM8740

liman324 пишет:

на пин reset контроллера подано +5 В через 10 К?

Нет, не подано. Но реализовать не проблема. Сделаю

17

Re: CS8416 + WM8740

Подтягивающие резисторы в норме.

18

Re: CS8416 + WM8740

Уже час как работает без зависаний. Всё-таки увеличение ёмкости электролитов свою роль сыграло. Резистор на Reset поставил на всякий случай. Но и без него всё ОК.

19

Re: CS8416 + WM8740

Проект меня заинтересовал. В заначке имеется всё. Только хотелось-бы dual-mono. Я в написании программ профан и по этому , прошу вас переписать под этот вариант программу. Заранее благодарен вам!

20

Re: CS8416 + WM8740

В регистре 4 есть настройки режима работы:

http://forum.rcl-radio.ru/uploads/images/2022/12/e1e38dd34cdf74fd3fb6adcec733284b.png

Можно подключить два WM8740, но управление должно быть разделено.

#define CS1   2  // ML WM8740
#define CLK1  3  // MC WM8740
#define DATA1 4  // MD WM8740

#define CS2   5  // ML WM8740
#define CLK2  6  // MC WM8740
#define DATA2 7  // MD WM8740

Но у меня нет возможности в железе собрать ЦАП с двумя WM8740 и протестировать скетч.

Так же в датащите указано что
To control the WM8740 in software differential mode register M4 must be written to. A ‘key’ register
write must be made to register M2 to allow access to register M4 which is ‘locked’ as default. Bits B5
to B8 of register M2 must be set to ‘1’ (0x01e0).
With register M4 ‘unlocked’, bits B4 and B5 may be used to set the required differential output mode;
normal stereo, reversed stereo, mono left or mono right, as shown in Table 18.

В регистр 2 биты с 5 по 8 должна быть установлена 1, для разрешения работы в указанном Вами режиме

Так же следует применить схему фильтра указанную в даташите для каждого WM8740

http://forum.rcl-radio.ru/uploads/images/2022/12/4a289c582d1f398354db0392e01b96d6.png


Я не уверен что этот режим мне удасться правильно запустить, не имея собранную схему

21

Re: CS8416 + WM8740

Здравствуйте! Схемные изменения меня не пугают. Не первый год с паяльником.  Разработать схему и плату, смогу (хоть и не по "феншую"). А вот с прошивкой - проблема! Сборкой смогу заняться только после праздников и соответственно протестировать прошивку (если вы её мне напишите). Все риски и проблемы я принимаю на себя. Соответственно о результатах отпишусь.

22

Re: CS8416 + WM8740

Хорошо, я подготовлю скетч и опубликую его на форуме.

23

Re: CS8416 + WM8740

Заранее Вас благодарю!

24

Re: CS8416 + WM8740

Скетч для теста готов

Значения регистров изменены для работы в дифференциальном режиме:

  // Write WM8740_1 SPI
  wireWrite_1(0b000100000000);//reg0
  wireWrite_1(0b001100000000);//reg1
  wireWrite_1(0b010111100000 + (dac_iw << 3));//reg2
  wireWrite_1(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite_1(0b110000010000);//reg4 [5:4] = 01 MONO LEFT

  // Write WM8740_2 SPI
  wireWrite_2(0b000100000000);//reg0
  wireWrite_2(0b001100000000);//reg1
  wireWrite_2(0b010111100000 + (dac_iw << 3));//reg2
  wireWrite_2(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite_2(0b110000110000);//reg4 [5:4] = 11 MONO RIGHT

Пины для подключения второй WM8740 указаны

#define CS_2   5  // ML WM8740_2
#define CLK_2  6  // MC WM8740_2
#define DATA_2 7  // MD WM8740_2

Тестируйте, если возникнут вопросы, пишите.

#define CS_1   2  // ML WM8740_1
#define CLK_1  3  // MC WM8740_1
#define DATA_1 4  // MD WM8740_1

#define CS_2   5  // ML WM8740_2
#define CLK_2  6  // MC WM8740_2
#define DATA_2 7  // MD WM8740_2
 
#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
      byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
      byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
      byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
      byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
      byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
      byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
      int a[3],vol,vol_d,menu,in,dem,form;
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
      unsigned long times,times1,oldPosition  = -999,newPosition;
      bool w,w1,www=1,mute;
      byte rol,dac_i2s,dac_iw,dem_res,for_dac,for_res,err,err_old;
 
void setup(){
   Wire.begin();
   Serial.begin(9600);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
   lcd.init();lcd.backlight();
   lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   pinMode(10,INPUT);   // SW энкодер
   pinMode(11,INPUT_PULLUP); // кнопка MUTE      
   pinMode(CS_1,OUTPUT);  // ML WM8740_1
   pinMode(CLK_1,OUTPUT); // MC WM8740_1
   pinMode(DATA_1,OUTPUT);// MD WM8740_1
   pinMode(CS_2,OUTPUT);  // ML WM8740_2
   pinMode(CLK_2,OUTPUT); // MC WM8740_2
   pinMode(DATA_2,OUTPUT);// MD WM8740_2
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении 
  vol = EEPROM.read(0);in = EEPROM.read(1);dem_res = EEPROM.read(3);for_dac = EEPROM.read(4);for_res = EEPROM.read(5);
  dac_i2s = EEPROM.read(6);dac_iw = EEPROM.read(7);rol = EEPROM.read(8);
   lcd.setCursor(0,0);lcd.print(" CS8416  WM8740 ");
   lcd.setCursor(0,1);lcd.print(" 24 bit  192kHz ");
  // Write WM8740_1 SPI
  wireWrite_1(0b000100000000);//reg0
  wireWrite_1(0b001100000000);//reg1
  wireWrite_1(0b010111100000 + (dac_iw << 3));//reg2
  wireWrite_1(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite_1(0b110000010000);//reg4 [5:4] = 01 MONO LEFT
  // Write WM8740_2 SPI
  wireWrite_2(0b000100000000);//reg0
  wireWrite_2(0b001100000000);//reg1
  wireWrite_2(0b010111100000 + (dac_iw << 3));//reg2
  wireWrite_2(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite_2(0b110000110000);//reg4 [5:4] = 11 MONO RIGHT
// Write 8416 I2C
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(2000);lcd.clear();
  // Write WM8740_1 SPI
  wireWrite_1(0b000100000000 + vol);//reg0
  wireWrite_1(0b001100000000 + vol);//reg1
  wireWrite_2(0b000100000000 + vol);//reg0
  wireWrite_2(0b001100000000 + vol);//reg1
  }
 
void loop(){ 
 /// MENU //////////////////////////////
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;};delay(200);lcd.clear();times=millis();w=1;w1=1;www=1;}
 /// MUTE /////////////////////////////
 if(digitalRead(11)==LOW && mute==0){mute=1; wireWrite_1(0b010000000001 + (dac_iw << 3));wireWrite_2(0b010000000001 + (dac_iw << 3));delay(300);www=1;} 
 if(digitalRead(11)==LOW && mute==1){mute=0; wireWrite_1(0b010000000000 + (dac_iw << 3));wireWrite_2(0b010000000000 + (dac_iw << 3));delay(300);www=1;} 
 
   if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;www=0;
     vol=vol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(vol<155){vol=155;}if(vol>255){vol=255;}
    wireWrite_1(0b000100000000 + vol);//reg0
    wireWrite_1(0b001100000000 + vol);//reg1
    wireWrite_2(0b000100000000 + vol);//reg0
    wireWrite_2(0b001100000000 + vol);//reg1
    Serial.println(vol);// vol = 155...255 step 0.5 dB
  }
  if(www==1||w==1){www=0;w=0;
      if(mute==1){         lcd.setCursor(0,0);lcd.print("MUTE    ");}
      if(err==0&&mute==0){ lcd.setCursor(0,0);lcd.print("VOLUME  ");}
      if(err==22&&mute==0){lcd.setCursor(0,0);lcd.print("ERROR   ");}
      if(err==8&&mute==0){ lcd.setCursor(0,0);lcd.print("NO SOUND");}
 
      lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in);
     vol_d=vol-156;a[0]=vol_d/10;a[1]=vol_d%10;
      for(i=0;i<2;i++){
      switch(i){
        case 0: e1=9,e2=10,e3=11;break;
        case 1: e1=12,e2=13,e3=14;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 //////// INPUT ////////////////////////////////////  
  if(menu==1){
    if (newPosition != oldPosition){oldPosition = newPosition;
     in=in-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(in<0){in=0;}if(in>7){in=7;}
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();}
  delay(10);
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("INPUT SELECTOR");  
  lcd.setCursor(0,1);lcd.print("COAXIAL "); lcd.print(in);lcd.print(" ");
  }}
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   /// DE-EMPHASIS //////////////////////////////////
  if(menu==2){
    if (newPosition != oldPosition){oldPosition = newPosition;
     dem=dem-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(dem<0){dem=0;}if(dem>3){dem=3;}
 
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("DE-EMPHASIS SEL");  
  lcd.setCursor(0,1);
  switch(dem){
  case 0: lcd.print("No De-emphasis");dem_res=0;break;
  case 1: lcd.print("44.1 kHz      ");dem_res=2;break;
  case 2: lcd.print("48.0 kHz      ");dem_res=3;break;
  case 3: lcd.print("32.0 kHz      ");dem_res=1;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   ///  FILTER ROLL-OFF //////////////////////////////////
  if(menu==3){
    if (newPosition != oldPosition){oldPosition = newPosition;
     rol=rol-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
      if(rol<0){rol=0;}if(rol>1){rol=1;}
 
  wireWrite_1(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite_2(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("ROLL-OFF SELECT ");  
  lcd.setCursor(0,1);
  switch(rol){
  case 0: lcd.print("Sharp");break;
  case 1: lcd.print("Slow ");break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   /// Serial Format Select //////////////////////////////////
  if(menu==4){
    if (newPosition != oldPosition){oldPosition = newPosition;
     form=form-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;
     if(form<0){form=0;}if(form>2){form=2;}
 
  Wire.beginTransmission(0x10);
  Wire.write (0x00);
  Wire.write (0b00000000);
  Wire.write (0b10000010);
  Wire.write (0b00000000 + (dem_res << 4));
  Wire.write (0b00000000);
  Wire.write (0b10000000 + (in << 3));
  Wire.write (0b10000000 + (for_res));
  Wire.write (0xFF);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.write (0x00);
  Wire.endTransmission();
  delay(10);
  wireWrite_1(0b010111100000 + (dac_iw << 3));//reg2
  wireWrite_1(0b011000000000 + dac_i2s + (rol << 3));//reg3
  wireWrite_2(0b010111100000 + (dac_iw << 3));//reg2
  wireWrite_2(0b011000000000 + dac_i2s + (rol << 3));//reg3
  delay(10);
  }
  if(www==1||w==1){www=0;w=0;
  lcd.setCursor(0,0);lcd.print("FORMAT SELECT");  
  lcd.setCursor(0,1);
  switch(form){
  case 0: lcd.print("L-Just 24 bit");dac_i2s=0;dac_iw=3;for_res=0;break;
  case 1: lcd.print("I2S    24 bit");dac_i2s=1;dac_iw=1;for_res=5;break;
  case 2: lcd.print("R-Just 24 bit");dac_i2s=0;dac_iw=2;for_res=8;break;
  }}}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
 
  /// read registr error 
  if(millis()-times1>1000){times1=millis();err = wireRead(0x10,0x0C);delay(10);}
  if(err!=err_old){err_old = err;www=1;}       
  /// EEPROM write
  if(millis()-times>10000 && w1==1){w1=0;EEPROM.update(0,vol);EEPROM.update(1,in);
  EEPROM.update(3,dem_res);EEPROM.update(4,for_dac);EEPROM.update(5,for_res);
  EEPROM.update(6,dac_i2s);EEPROM.update(7,dac_iw);EEPROM.update(8,rol);
  menu=0;www=1;if(menu!=0){lcd.clear();}}
  delay(100);
  }// loop  
 
void wireWrite_1(int data_1){        // SPI
  digitalWrite(CLK_1,HIGH);digitalWrite(CS_1,HIGH);delay(1);
     for(int i = 15; i >= 0; i--){
        digitalWrite(CLK_1,LOW);
        digitalWrite(DATA_1, (data_1 >> i) & 0x01);delay(1);
        digitalWrite(CLK_1,HIGH);delay(1);}
  digitalWrite(CS_1,LOW);delay(1);digitalWrite(CS_1,HIGH);
  }
void wireWrite_2(int data_2){        // SPI
  digitalWrite(CLK_2,HIGH);digitalWrite(CS_2,HIGH);delay(1);
     for(int i = 15; i >= 0; i--){
        digitalWrite(CLK_2,LOW);
        digitalWrite(DATA_2, (data_2 >> i) & 0x01);delay(1);
        digitalWrite(CLK_2,HIGH);delay(1);}
  digitalWrite(CS_2,LOW);delay(1);digitalWrite(CS_2,HIGH);
  }  
 
byte wireRead(int addr, int reg){ // I2C
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  
 
void to_Timer(){newPosition = myEnc.read()/4;}

25

Re: CS8416 + WM8740

Большое вам спасибо! После беглого просмотра возник всего один вопрос: а разве выводы CLK и  DATA у первой и второй WM8740 не равноценны и не стоит ли их объединить?