| Ваш IP: 3.237.105.210 | Online(21) - гости: 9, боты: 12 | Загрузка сервера: 2.47 ::::::::::::

DAC CS8416 + WM8740 (Arduino)

Внешний звуковой ЦАП под управлением платы Arduino (Nano) состоит из нескольких компонентов:

  • Ресивер CS8416
  • ЦАП WM8740
  • ФНЧ на NE5532
  • Источника питания
  • Платы Arduino (Nano)
  • Индикатор LCD1602 (I2C)
  • Органы регулировки — экнодер, кнопка

Параметры ресивера CS8416:

  • Напряжение питания:
    • +3.3 V Analog Supply (VA)
    • +3.3 V Digital Supply (VD)
    • +3.3 V or +5.0 V Digital Interface Supply (VL)
  • Входной формат данных: S/PDIF
  • Выходной формат данных:
    • Left-Justified
    • Right-Justified
    • I2S
  • Разрядность 24 бит
  • Частота дискредитации 192 кГц
  • Фильтр De-emphasis:
    • No De-emphasis
    • 32 kHz
    • 48 kHz
    • 44.1 kHz
  • Кол-во входов: 8
  • Управление: I2C

Параметры ЦАП на WM8740:

  • Напряжение питания:
    • +5 V Analog Supply (AVDD)
    • +5 V Digital Supply (DVDD)
  • Входной формат данных:
    • Left-Justified
    • Right-Justified
    • I2S
  • Разрядность 24 бит
  • Частота дискредитации 192 кГц
  • Уровень гармонических искажений THD+N
    • -104 dB (0dB)
    • -117 dB (-60 dB)
  • Отношение сигнал/шум 107 dB
  • Фильтр De-emphasis:
    • No De-emphasis
    • 32 kHz
    • 48 kHz
    • 44.1 kHz
  • Фильтр ROLL-OFF:
    • Sharp
    • Slow
  • Управление: SPI

Внешний ЦАП достаточно простой, состоит из недорогих компонентов. Ресивер CS8416 управляется при помощи шины I2C, содержит 8 входов S/PDIF (Toslink), работает по трем выходным форматам данных (Left-Justified, Right-Justified, I2S), содержит переключаемый фильтр De-emphasis, содержит систему опознавания ошибок. ЦАП на WM8740 так же работает на прием трех форматов данных (Left-Justified, Right-Justified, I2S), содержит переключаемые фильтры De-emphasis и ROLL-OFF, имеет систему MUTE, регулятор громкости на 255 шагов (127 дБ), каждый шаг 0,5 дБ, программно число шагов ограничено от 155 до 255 значений, что соответствует диапазону регулировки от -50 до 0 дБ.

Вся информация о текущих настройках внешнего ЦАП отображается на индикаторе LCD1602 ( с модулем I2C), регулировка всех параметров осуществляется при помощи энкодера KY-040, параметр MUTE активируется отдельной кнопкой.

Схема ресивера

Схема ЦАП

Схема ФНЧ

Схема источника питания (стабилизаторов)

Для питания внешнего ЦАПа рекомендуется использовать три независимых источника питания, который состоит из одного трансформатора с тремя независимыми вторичными обмотками,  одна из которых имеет отвод от середины для двух полярного источника питания. Каждый источник питания имеет свой диодный мост. При этом аналоговая и цифровая земля объединяются через дроссель. Дополнительно как можно ближе к микросхемам по цепи питания устанавливаются фильтрующие конденсаторы 0,1 и 22 мкФ.

Arduino

  • Меню громкости (99 шагов), индикация выбранного входа, индикатор MUTE и ERROR
  • Меню выбора входа

  • Меню фильтра De-emphasis
  • Меню фильтра ROLL-OFF
  • Меню выбора выходного формата

 

#define CS   2  // ML WM8740
#define CLK  3  // MC WM8740
#define DATA 4  // MD WM8740
 
#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // https://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // https://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;}

Добавить комментарий

Войти с помощью: 

Случайные статьи

  • УМЗЧ 80 Вт на LM3875

    УМЗЧ 80 Вт на LM3875

    На ИМС LM3875 можно собрать простой но достаточно мощный УМЗЧ, выходная мощность усилителя 80 Вт. LM3875 это высококачественный усилитель мощности звуковой частоты, способный выдавать 56 Вт непрерывной средней мощности на нагрузку 8 Ом при КНИ не более 0,1%, имеет частотный диапазон от 20 гц до 20 кГц . При подключении двух …Подробнее...
  • Источник питания 0…13.8В 10А

    На рисунке показана схема источника питания  с выходным напряжением от 0 до 13,8 (16В) с максимальным током нагрузки в 10А. В схеме используется микросхема LM723 и три транзистора, два из которых силовые — 2N3055.      Регулировка выходного напряжения осуществляется потенциометром VR1 (1К).Транзисторы VT1 VT2 должны быть установлены на радиаторы, …Подробнее...
  • Вольтметр — светодиодный индикатор

    R1, R2, R3 — делители напряжения в диапазонах 0-1,2В, 0-12В и 0-120В. Вольтметр индикатор собран на микросхеме LM3914. Ток протекающий через каждый светодиод может достигать 30мА. R4 — регулирует яркость светодиодов. Каждый светодиод имеет шаг 1,2В (в диапазоне 12В). Изменив значения делителей напряжения R1 R2 R3 Вы можете самостоятельно подобрать …Подробнее...
  • Универсальный видео разветвитель

    Данный видео разветвитель может позволить записывать видео сигнал от одного источника на десять видеомагнитофонов(при условии что видеомагнитофоны не оказывают шунтирующего действия друг на друга). Транзисторы используемые в схеме — КТ315 любые или КТ3012 КТ342 КТ503. Конденсаторы на 33 мкФ можно заменить на другие от 22 до 47 мкФ. С32 на …Подробнее...
  • Миниатюрный радиоприемник на ZN414

    Миниатюрный радиоприемник на ZN414

    На микросхеме ZN414 (аналоги — TA7642, MK484) можно собрать простой, миниатюрный АМ приемник СВ-ДВ диапазона. Микросхема имеет всего три вывода и похожа на транзистор, она представляют собой высокочастотный тракт приемника прямого усиления, содержащий усилитель радиочастоты (УРЧ), детектор и систему автоматической регулировки усиления (АРУ). УРЧ имеет большой коэффициент усиления и высокое входное сопротивление, что позволяет …Подробнее...