Тема: DAC WM8804 + AK4396 — 24bit 192kHz (Arduino) - доработка
Основная статья - http://rcl-radio.ru/?p=92642
Изменен вывод состояния фильтров на экран
#define CS 10 // CSN AK4396
#define MOSI 11 // CDTI AK4396
#define SCK 13 // CCLK AK4396
#define RES 2 // PDN AK4396
#include <SPI.h>
#include <EEPROM.h>
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.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};
unsigned long times,oldPosition = -999,newPosition,times1;
int w,vol,mute,code_mute,in,w2,a[3],menu,dem,err,err_old,roll;
int db[38]={0,1,2,3,4,5,6,7,8,9,10,11,13,15,17,19,22,25,28,32,36,40,45,51,57,64,72,80,90,100,112,126,142,159,178,200,224,255};
byte u,d1,d2,d3,d4,d5,d6,e1,e2,e3;
void setup(){
Wire.begin();SPI.begin();
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);
MsTimer2::set(1, to_Timer);MsTimer2::start();
if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
lcd.setCursor(5,0);lcd.print("WM8804");
lcd.setCursor(5,1);lcd.print("AK4396");
pinMode(CS,OUTPUT);
pinMode(RES,OUTPUT);
pinMode(5,INPUT_PULLUP); // кнопка MUTE
pinMode(7,INPUT); // кнопка SW энкодера MENU
vol = EEPROM.read(0);dem = EEPROM.read(2); roll = EEPROM.read(3);
delay(1000);
digitalWrite(RES,HIGH);ak();lcd.clear(); // AK4396 ON
}// setup
void loop(){
/// MENU //////////////////////////////
if(digitalRead(7)==LOW){menu++;if(menu>2){menu=0;};delay(100);lcd.clear();w=1;times=millis();w2=1;}
/// MUTE ///////////////////
if(digitalRead(5)==LOW&&mute==0&&menu==0){mute=1;delay(200);WriteAK4396(0b0010001100000000);WriteAK4396(0b0010010000000000);}
if(digitalRead(5)==LOW&&mute==1&&menu==0){mute=0;delay(200);WriteAK4396(0b0010001100000000 + db[vol]);WriteAK4396(0b0010010000000000 + db[vol]);}
/// VOLUME ///////////////////////////////////////////////////
if(menu==0){
if (newPosition != oldPosition){oldPosition = newPosition;
vol=vol+newPosition;myEnc.write(0);newPosition=0;w=1;times=millis();w2=1;w=1;mute=0;
if(vol>37){vol=37;}if(vol<0){vol=0;}
ak();}
lcd.setCursor(0,0);
if(mute==1){lcd.print("MUTE ");}else{lcd.print("VOLUME ");}
lcd.setCursor(0,1);
switch(roll){
case 0: lcd.print("SH ");break;
case 1: lcd.print("SL ");break;}
switch(dem){
case 1: lcd.print(" ");break;
case 0: lcd.print("44.1");break;
case 3: lcd.print("32.0");break;
case 2: lcd.print("48.0");break;}
if(w2==1){w2=0;
a[0]=vol/10;a[1]=vol%10;
for(u=0;u<2;u++){
switch(u){
case 0: e1=9,e2=10,e3=11;break;
case 1: e1=12,e2=13,e3=14;break;
}
switch(a[u]){
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);
}}
} // volume end
/// DE-EMPHASIS //////////////////////////////////
if(menu==1){
if (newPosition != oldPosition){oldPosition = newPosition;
dem=dem+newPosition;myEnc.write(0);newPosition=0;w=1;times=millis();w2=1;
if(dem<0){dem=3;}if(dem>3){dem=0;}
ak();
}
if(w2==1){w2=0;
lcd.setCursor(0,0);lcd.print("DE-EMPHASIS SEL");
lcd.setCursor(0,1);
switch(dem){
case 1: lcd.print("No De-emphasis");break;
case 0: lcd.print("44.1 kHz ");break;
case 3: lcd.print("32.0 kHz ");break;
case 2: lcd.print("48.0 kHz ");break;
}}}
/// Roll-off Filter //////////////////////////////////
if(menu==2){
if (newPosition != oldPosition){oldPosition = newPosition;
roll=roll+newPosition;myEnc.write(0);newPosition=0;w=1;times=millis();w2=1;
if(roll<0){roll=1;}if(roll>1){roll=0;}
ak();
}
if(w2==1){w2=0;
lcd.setCursor(0,0);lcd.print("Roll-off Filter");
lcd.setCursor(0,1);
switch(roll){
case 0: lcd.print("Sharp");break;
case 1: lcd.print("Slow ");break;
}}}
if(millis()-times>5000 && w==1){w=0;EEPROM.update(0,vol);EEPROM.update(2,dem);EEPROM.update(3,roll);menu=0;lcd.clear();w2=1;}
delay(100);
}// loop
void WriteAK4396(uint16_t Data){
for(int p=0;p<2;p++){
SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV16, MSBFIRST, SPI_MODE0));
digitalWrite(CS, LOW);
delayMicroseconds(10);
SPI.transfer16(Data);
digitalWrite(CS, HIGH);
SPI.endTransaction();
}}
void ak(){
WriteAK4396(0b0010000000000111); // control 00H
WriteAK4396(0b0010000100010010 + (dem << 1) + (roll << 5)); // control 01H -- [4:3]=10 120-216kHz -- [2:1]=dem off/44.1/32/48 -- [5]=roll
WriteAK4396(0b0010001000000000); // control 02H
WriteAK4396(0b0010001100000000 + db[vol]); // volume left 03H
WriteAK4396(0b0010010000000000 + db[vol]); // volume right 04H
}
void to_Timer(){newPosition = myEnc.read()/4;}