audiohobby.ru audiohobby.ru

Комментарии

0
Le81 Le81 Документация к ES9039Q2M 14 часов назад

Естьполный скетч, старт — сразу Volume; кнопка — второе меню с Path, Bypass IIR/FIR2/FIR4, ASRC On/Off, THD C2, THD C3, Save/Load/Reset. THD — сразу применяется при вращении; одно значение пишется в оба канала

Если кому-то нужно!

0
Digital _Ivan90 Digital _Ivan90 Профессиональный ЦАП AH-D19-PRO на BD34352EKV 17 часов назад

Проект очень интересный, поздравляю!!!

Как человек, один раз собравший цап с «нуля», понимаю, что это требует просто огромных усилий и времени!!!

Я не слышал раньше про эту фирму, скачал даташит на цап, разобрало любопытство, насколько звук их чипов достоверный и естественный… И намного — ли хуже измерения с резистором в i/u...

С уважением, Иван.

0
Digital _Ivan90 Digital _Ivan90 Профессиональный ЦАП AH-D19-PRO на BD34352EKV 18 часов назад

Мне нравится топология преобразователя ток — напряжение и фнч, применённая Виктором Корсаковым с ad1955, звучит, мне кажется, вполне неплохо...

https://www.google.com/url?sa=t&source=web&rct=j&o...

Это ещё вариант...

0
User4220 User4220 Высококачественный ЦАП AH-D6.1 на AK4493 / AK4490, премиальная версия AH-D6 2 дня назад

Думаю, что да. Продублируйте вопрос в ветке ЦАПА на AK4497. Если там тоже ответят также, то можете смело менять.

0
excellenze excellenze Система Динамического Подмагничивания на одном транзисторе 2 дня назад

Данная схема была неоднократно и успешно применена в Яузе-221. А2, Плата коммутации, токоограничивающие сопротивления R25 и R26, оба по 33к. Вход для СДП справа по схеме (точки соединения R25, R28, C7 и R26, R29, C8), выход для СДП слева, те же сопротивления R25 и R26. (Идут к контактам 2 и 6 разъема Х8). По словам естествоиспытателя, запись на магнитную ленту Тип 1 (обычная, Fe2O3) ничем не уступает источнику. Вложение p221.zip

Да, хочу отметить, что следует соблюдать цоколевку транзистора.

0
0
User4220 User4220 Высококачественный ЦАП AH-D6.1 на AK4493 / AK4490, премиальная версия AH-D6 2 дня назад

Распаянные на DIP-переходники OPA1612 и OPA1656 в аналоговом фильтре просто менял местами. Всё отлично взаимозаменяется. У OPA1612 немного другой звук получается, чем 1656, но понравилось.

0
fertovoi fertovoi Высококачественный ЦАП AH-D6.1 на AK4493 / AK4490, премиальная версия AH-D6 2 дня назад

а можно ли аналоговый фильтр этого ЦАПА применить к AK4497EQ с OPA1612 в аналоговом фильтре или обязательно ставить OPA1656?

0
caleb caleb Продам собранную плату ЦАП AH-D19-PRO на BD34352EKV 3 дня назад

Ух какой вкусный цап… И цена, по сути за детали с такой хорошей комплектацией. Купил бы, но у меня уже есть.

+1
zirkony zirkony Документация к ES9039Q2M 4 дня назад

… или временно загрузить на пастебин, там можно указать срок хранение

Иначе вот такое получается, как на картинке

+5
Le81 Le81 Документация к ES9039Q2M 4 дня назад

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

#include <EEPROM.h>

/* =========================

ПОДКЛЮЧЕНИЯ / АДРЕСА

========================= */

#define DAC_ADDR 0x49

#define LCD_ADDR 0x27

LiquidCrystal_I2C lcd(LCD_ADDR, 16, 2);

#define ENC_A 2

#define ENC_B 3

#define BTN 4

#define CHIP_EN_PIN 7 // HIGH=ON, LOW=RESET

/* =========================

РЕГИСТРЫ ES9039Q2M (DEC)

========================= */

#define REG_SYS 0x00

#define REG_IFACE_POL 0x03

#define REG_CLKCFG 0x04

#define REG_PLL_BW 0x05

#define REG_AUTO_INPUT 57

#define REG_SLOT_L 64

#define REG_SLOT_R 65

#define REG_VOL_L 74

#define REG_VOL_R 75

#define REG_FILTER 88

#define REG_PATH 90

#define REG_THD_C2_LSB 91

#define REG_THD_C3_LSB 107

#define REG_AM_ENABLE 123

#define REG_AM_TIME_L 124

#define REG_S1 0x1C

#define REG_S2 0x1D

#define REG_ID 225

/* =========================

ПРОТОТИПЫ

========================= */

bool wr(uint8_t r, uint8_t v);

bool wr16(uint8_t addrLSB, uint16_t val);

bool rd(uint8_t r, uint8_t &v);

bool pingDAC();

void chipOn();

void chipOff();

void chipReset(uint16_t ms=400);

bool lockStatus();

uint32_t fsFromS2();

void volWriteLR(uint8_t vL,uint8_t vR);

void setFilter(uint8_t f);

void writePathConfig();

void applySafe_VolBal();

void applySafe_Filter();

void applySafe_Path();

void applyAutoMute();

void applyTHD_C2();

void applyTHD_C3();

void queueApply(bool softR=false);

void runPending();

void showStatus();

void drawMenu();

void doAction(uint8_t idx);

void encISR();

void pollBtn();

void onChangeSafe(uint8_t code);

void onChangeDanger(uint8_t what);

/* =========================

СОСТОЯНИЕ / МЕНЮ

========================= */

uint8_t g_volBase=0; // 0..255 (0=0 dB)

int8_t g_balance=0; // -24..+24 (≈±12 dБ)

uint8_t g_dfilt=0; // 0..7

uint8_t g_path=0; // 0=ST,1=MonoL,2=MonoR,3=Swap

// bypass биты REG_PATH

bool g_bypIIR=false;

bool g_bypFIR4=false;

bool g_bypFIR2=false;

// интерфейс / клок

uint8_t g_pol=0; // 0..3

uint8_t g_pll=0x04; // 0x02..0x08 обычно

bool g_autoClk=true;

bool g_autoIn =true;

bool g_hardtrue; // «опасные» не писать

uint16_t g_settle=700; // мс после «опасных»

// AutoMute

bool g_amCh1=true;

bool g_amCh2=true;

bool g_amRampGND=true; // bit11

uint16_t g_amTime=0x00F; // [10:0]

// THD (signed 16-bit)

int16_t g_c2_L=0, g_c2_R=0;

int16_t g_c3_L=0, g_c3_R=0;

/* ===== Планировщик «опасных» ===== */

struct Pending { bool polarity=false, pll=false, autoclk=false, autoin=false, softReset=false; } pend;

/* ===== EEPROM / пресеты ===== */

#define CFG_VERSION 0x39 // меняй при правке структуры

struct Config {

uint8_t version;

uint8_t volBase; int8_t balance; uint8_t dfilt; uint8_t path;

bool bypIIR, bypFIR4, bypFIR2;

uint8_t pol, pll; bool autoClk, autoIn;

bool hardOnly; uint16_t settle;

bool amCh1, amCh2, amRamp; uint16_t amTime;

int16_t c2L, c2R, c3L, c3R;

uint8_t autosave;

uint16_t crc;

};

uint16_t crc16(const uint8_t* p, size_t n){

uint16_t c=0xFFFF;

for(size_t i=0;i<n;i++){ c ^= p[i]; for(uint8_t b=0;b<8;b++){ c = (c&1)?(c>>1)^0xA001:(c>>1); } }

return c;

}

#define EE_ADDR_LAST 0

#define EE_ADDR_PRE1 128

#define EE_ADDR_PRE2 256

#define EE_ADDR_PRE3 384

bool g_autosave=true;

uint8_t g_presetSel=1; // 1..3

/* ===== UI ===== */

volatile int16_t enc_delta=0;

bool btn_short=false, btn_lfalse, btn_dbl=false;

uint8_t menu_idx=0; bool edit=false;

const char* MENU[]={

// базовые

«Status»,«Volume»,«Balance»,«Filter»,«Path»,

// bypass

«Bypass IIR»,«Bypass FIR4»,«Bypass FIR2»,

// AutoMute

«AM Ch1»,«AM Ch2»,«AM RampGND»,«AM Time»,

// THD

«THD C2 L»,«THD C2 R»,«THD C3 L»,«THD C3 R»,

// интерфейс/PLL

«Polarity»,«DPLL BW»,«AutoClock»,«AutoInput»,

// пресеты

«Preset Load»,«Preset Save»,«Autosave»,

// прочее

«HardOnly»,«Reset»

};

const uint8_t MCNT = sizeof(MENU)/sizeof(MENU[0]);

/* =========================

I2C helpers

========================= */

bool wr(uint8_t r, uint8_t v){

Wire.beginTransmission(DAC_ADDR);

Wire.write®; Wire.write(v);

return (Wire.endTransmission()==0);

}

bool wr16(uint8_t addrLSB, uint16_t val){

return wr(addrLSB, (uint8_t)(val & 0xFF))

&& wr(addrLSB+1, (uint8_t)((val>>8)&0xFF));

}

bool rd(uint8_t r, uint8_t &v){

Wire.beginTransmission(DAC_ADDR); Wire.write®;

if(Wire.endTransmission(false)!=0) return false;

if(Wire.requestFrom((int)DAC_ADDR,1)!=1) return false;

v=Wire.read(); return true;

}

bool pingDAC(){ Wire.beginTransmission(DAC_ADDR); return (Wire.endTransmission()==0); }

/* =========================

ЧИП / СТАТУС

========================= */

void chipOn(){ pinMode(CHIP_EN_PIN,OUTPUT); digitalWrite(CHIP_EN_PIN,HIGH); }

void chipOff(){ digitalWrite(CHIP_EN_PIN,LOW); }

void chipReset(uint16_t ms){ chipOff(); delay(ms); chipOn(); delay(150); }

bool lockStatus(){ uint8_t s1=0; if(!rd(REG_S1,s1)) return false; return (s1&0x80)!=0; }

uint32_t fsFromS2(){

uint8_t s2=0; if(!rd(REG_S2,s2)) return 0; switch(s2&0x0F){

case 0: return 44100; case 1: return 48000; case 2: return 88200; case 3: return 96000;

case 4: return 176400; case 5: return 192000; case 6: return 384000; default: return 0; }

}

/* =========================

ЗАПИСИ В ЦАП (без mute)

========================= */

void volWriteLR(uint8_t vL,uint8_t vR){ wr(REG_VOL_L,vL); wr(REG_VOL_R,vR); }

void setFilter(uint8_t f){ wr(REG_FILTER, f & 0x07); }

void writePathConfig(){

uint8_t v=0;

if(g_bypIIR) v|=0x04;

if(g_bypFIR4) v|=0x02;

if(g_bypFIR2) v|=0x01;

wr(REG_PATH, v);

switch(g_path){

default:

case 0: wr(REG_SLOT_L,0x00); wr(REG_SLOT_R,0x01); break;

case 1: wr(REG_SLOT_L,0x00); wr(REG_SLOT_R,0x00); break;

case 2: wr(REG_SLOT_L,0x01); wr(REG_SLOT_R,0x01); break;

case 3: wr(REG_SLOT_L,0x01); wr(REG_SLOT_R,0x00); break;

}

}

void applySafe_VolBal(){

int16_t vL=g_volBase, vR=g_volBase;

if(g_balance>0) vL+=g_balance; else if(g_balance<0) vR+=(-g_balance);

if(vL<0)vL=0; if(vL>255)vL=255; if(vR<0)vR=0; if(vR>255)vR=255;

volWriteLR((uint8_t)vL,(uint8_t)vR);

}

void applySafe_Filter(){ setFilter(g_dfilt); }

void applySafe_Path(){ writePathConfig(); }

void applyAutoMute(){

uint8_t en = (g_amCh1?1:0) | (g_amCh2?2:0);

wr(REG_AM_ENABLE, en);

uint16_t t = ((g_amRampGND?1:0)<<11) | (g_amTime & 0x07FF);

wr16(REG_AM_TIME_L, t);

}

// THD: LSB->MSB, [15:0]=L, [31:16]=R

void applyTHD_C2(){

uint16_t wL=(uint16_t)g_c2_L, wR=(uint16_t)g_c2_R;

wr(REG_THD_C2_LSB+0,(uint8_t)(wL&0xFF));

wr(REG_THD_C2_LSB+1,(uint8_t)((wL>>8)&0xFF));

wr(REG_THD_C2_LSB+2,(uint8_t)(wR&0xFF));

wr(REG_THD_C2_LSB+3,(uint8_t)((wR>>8)&0xFF));

}

void applyTHD_C3(){

uint16_t wL=(uint16_t)g_c3_L, wR=(uint16_t)g_c3_R;

wr(REG_THD_C3_LSB+0,(uint8_t)(wL&0xFF));

wr(REG_THD_C3_LSB+1,(uint8_t)((wL>>8)&0xFF));

wr(REG_THD_C3_LSB+2,(uint8_t)(wR&0xFF));

wr(REG_THD_C3_LSB+3,(uint8_t)((wR>>8)&0xFF));

}

/* =========================

ОПАСНЫЕ — ПЛАНИРОВЩИК

========================= */

void queueApply(bool softR){ if(!g_hardOnly) pend.softReset |= softR; }

void runPending(){

static bool busy=false;

if(g_hardOnly){ pend=Pending(); busy=false; return; }

if(busy) return;

if(!(pend.polarity||pend.pll||pend.autoclk||pend.autoin||pend.softReset)) return;

busy=true;

if(pend.softReset){ wr(REG_SYS,0x80); delay(6); }

wr(REG_SYS,0x02); // аналог включен

if(pend.polarity) wr(REG_IFACE_POL,(g_pol&0x03));

if(pend.autoclk) wr(REG_CLKCFG, g_autoClk?0x40:0x00);

if(pend.pll) wr(REG_PLL_BW, g_pll);

if(pend.autoin) wr(REG_AUTO_INPUT,g_autoIn?0x01:0x00);

writePathConfig();

applySafe_VolBal();

setFilter(g_dfilt);

delay(g_settle);

pend=Pending();

busy=false;

}

/* =========================

EEPROM / PRESETS

========================= */

void cfgFromGlobals(Config &c){

c.version=CFG_VERSION;

c.volBase=g_volBase; c.balance=g_balance; c.dfilt=g_dfilt; c.path=g_path;

c.bypIIR=g_bypIIR; c.bypFIR4=g_bypFIR4; c.bypFIR2=g_bypFIR2;

c.pol=g_pol; c.pll=g_pll; c.autoClk=g_autoClk; c.autoIn=g_autoIn;

c.hardg_hardOnly; c.settle=g_settle;

c.amCh1=g_amCh1; c.amCh2=g_amCh2; c.amRamp=g_amRampGND; c.amTime=g_amTime;

c.c2L=g_c2_L; c.c2R=g_c2_R; c.c3L=g_c3_L; c.c3R=g_c3_R;

c.autosave=g_autosave?1:0;

c.crc=0;

c.crc=crc16((uint8_t*)&c, sizeof(Config)-2);

}

void globalsFromCfg(const Config &c){

g_volBase=c.volBase; g_balance=c.balance; g_dfilt=c.dfilt; g_path=c.path;

g_bypIIR=c.bypIIR; g_bypFIR4=c.bypFIR4; g_bypFIR2=c.bypFIR2;

g_pol=c.pol; g_pll=c.pll; g_autoClk=c.autoClk; g_autoIn=c.autoIn;

g_hardc.hardOnly; g_settle=c.settle;

g_amCh1=c.amCh1; g_amCh2=c.amCh2; g_amRampGND=c.amRamp; g_amTime=c.amTime;

g_c2_L=c.c2L; g_c2_R=c.c2R; g_c3_L=c.c3L; g_c3_R=c.c3R;

g_autosave=(c.autosave!=0);

}

bool eepromWrite(int base, const Config &c){

Config tmp=c;

for(unsigned i=0;i<sizeof(Config);++i) EEPROM.update(base+i, ((uint8_t*)&tmp)[i]);

return true;

}

bool eepromRead(int base, Config &c){

for(unsigned i=0;i<sizeof(Config);++i) ((uint8_t*)&c)[i]=EEPROM.read(base+i);

if(c.version!=CFG_VERSION) return false;

uint16_t calc=crc16((uint8_t*)&c, sizeof(Config)-2);

return (calc==c.crc);

}

void loadSlot(uint8_t slot){

int addr = (slot==1)?EE_ADDR_PRE1: (slot==2)?EE_ADDR_PRE2: EE_ADDR_PRE3;

Config c; if(eepromRead(addr,c)){ globalsFromCfg©; }

}

void saveSlot(uint8_t slot){

int addr = (slot==1)?EE_ADDR_PRE1: (slot==2)?EE_ADDR_PRE2: EE_ADDR_PRE3;

Config c; cfgFromGlobals©; eepromWrite(addr,c);

}

void autosaveWrite(){

if(!g_autosave) return;

static uint32_t last=0;

uint32_t now=millis();

if(now-last<1500) return; // экономим ресурс EEPROM

last=now;

Config c; cfgFromGlobals©; eepromWrite(EE_ADDR_LAST,c);

}

void autosaveLoadOnBoot(){

Config c; if(eepromRead(EE_ADDR_LAST,c)){ globalsFromCfg©; }

}

/* =========================

ЭКРАН / МЕНЮ

========================= */

void showStatus(){

lcd.clear();

lcd.print(lockStatus()? «Lock:Y »:«Lock:N „);

lcd.print(“P:»); lcd.print(g_pol);

lcd.setCursor(0,1);

uint32_t fs=fsFromS2();

if(fs){ lcd.print(«Fs:»); lcd.print(fs/1000); lcd.print(«k „); }

else { lcd.print(“Fs:? „); }

}

void drawMenu(){

lcd.clear();

lcd.print(“[»); lcd.print(menu_idx+1); lcd.print("/"); lcd.print(MCNT); lcd.print("] ");

lcd.print(MENU[menu_idx]);

lcd.setCursor(0,1);

switch(menu_idx){

case 0: lcd.print(«Status»); break;

case 1: lcd.print(«Vol: „); lcd.print(g_volBase); break;

case 2: lcd.print(“Bal: „); lcd.print((int)g_balance); break;

case 3: lcd.print(“Filt: „); lcd.print(g_dfilt); break;

case 4: lcd.print(“Path: „); lcd.print(g_path); break;

case 5: lcd.print(“Byp IIR: „); lcd.print(g_bypIIR ?“Y»:«N»); break;

case 6: lcd.print(«Byp FIR4: „); lcd.print(g_bypFIR4?“Y»:«N»); break;

case 7: lcd.print(«Byp FIR2: „); lcd.print(g_bypFIR2?“Y»:«N»); break;

case 8: lcd.print(«AM Ch1: „); lcd.print(g_amCh1?“ON»:«OFF»); break;

case 9: lcd.print(«AM Ch2: „); lcd.print(g_amCh2?“ON»:«OFF»); break;

case 10: lcd.print(«AM RampGND: „); lcd.print(g_amRampGND?“Y»:«N»); break;

case 11: lcd.print(«AM Time: „); lcd.print(g_amTime); break;

case 12: lcd.print(“THD C2 L: „); lcd.print(g_c2_L); break;

case 13: lcd.print(“THD C2 R: „); lcd.print(g_c2_R); break;

case 14: lcd.print(“THD C3 L: „); lcd.print(g_c3_L); break;

case 15: lcd.print(“THD C3 R: „); lcd.print(g_c3_R); break;

case 16: lcd.print(“Pol: „); lcd.print(g_pol); break;

case 17: lcd.print(“DPLL:0x»); lcd.print(g_pll,HEX); break;

case 18: lcd.print(«AutoClk: „); lcd.print(g_autoClk?“ON»:«OFF»); break;

case 19: lcd.print(«AutoIn: „); lcd.print(g_autoIn ?“ON»:«OFF»); break;

case 20: lcd.print(«Load P»); lcd.print(g_presetSel); break;

case 21: lcd.print(«Save P»); lcd.print(g_presetSel); break;

case 22: lcd.print(«Autosave: „); lcd.print(g_autosave?“ON»:«OFF»); break;

case 23: lcd.print(«HardOnly: „);lcd.print(g_hardOnly?“YES»:«NO»); break;

case 24: lcd.print(«Reset CHIP_EN»); break;

}

}

/* =========================

ВВОД / ОБРАБОТКА

========================= */

void encISR(){

static uint8_t prev=0;

uint8_t cur=(digitalRead(ENC_A)<<1)|digitalRead(ENC_B);

static const int8_t tab[4][4]={{0,-1,+1,0},{+1,0,0,-1},{-1,0,0,+1},{0,+1,-1,0}};

enc_delta+=tab[prev][cur]; prev=cur;

}

void pollBtn(){

static uint32_t t0=0,down=0; static bool last=false;

static uint32_t lastUp=0; static bool clickArmed=false;

const uint16_t DEB=20,L900, DBL=350;

bool raw=(digitalRead(BTN)==LOW); uint32_t now=millis();

if(raw!=last && (now-t0)>DEB){

t0=now; last=raw;

if(raw){ down=now; }

else{

uint32_t dur=now-down;

if(dur<600){

if(clickArmed && (now-lastUp)<DBL){ btn_dbl=true; clickArmed=false; }

else { btn_short=true; clickArmed=true; lastUp=now; }

}else if(dur>=LONG){ btn_ltrue; clickArmed=false; }

}

}

if(clickArmed && (now-lastUp)>=DBL) clickArmed=false;

}

void onChangeSafe(uint8_t code){

switch(code){

case 1: applySafe_VolBal(); autosaveWrite(); break;

case 2: applySafe_Filter(); autosaveWrite(); break;

case 3: applySafe_Path(); autosaveWrite(); break;

case 4: applyAutoMute(); autosaveWrite(); break;

case 5: applyTHD_C2(); autosaveWrite(); break;

case 6: applyTHD_C3(); autosaveWrite(); break;

}

}

void onChangeDanger(uint8_t what){

if(g_hardOnly) return;

if(what==10) pend.polarity=true;

if(what==11) pend.pll=true;

if(what==12) pend.autoclk=true;

if(what==13) pend.autoin=true;

queueApply(false);

autosaveWrite();

}

void doAction(uint8_t idx){

if(idx==0){ showStatus(); return; }

if(idx==20){ // Load preset

loadSlot(g_presetSel);

writePathConfig(); setFilter(g_dfilt); applySafe_VolBal();

applyAutoMute(); applyTHD_C2(); applyTHD_C3();

drawMenu(); return;

}

if(idx==21){ // Save preset

saveSlot(g_presetSel);

drawMenu(); return;

}

if(idx==24){

chipReset();

wr(REG_SYS,0x02);

writePathConfig(); setFilter(g_dfilt); applySafe_VolBal();

applyAutoMute(); applyTHD_C2(); applyTHD_C3();

drawMenu(); return;

}

}

/* =========================

SETUP / LOOP

========================= */

void setup(){

chipOn();

Wire.begin();

lcd.init(); lcd.backlight();

pinMode(ENC_A,INPUT_PULLUP); pinMode(ENC_B,INPUT_PULLUP); pinMode(BTN,INPUT_PULLUP);

attachInterrupt(digitalPinToInterrupt(ENC_A), encISR, CHANGE);

attachInterrupt(digitalPinToInterrupt(ENC_B), encISR, CHANGE);

lcd.print(«ES9039Q2M +EEPROM»);

lcd.setCursor(0,1);

if(pingDAC()){ uint8_t id=0; rd(REG_ID,id); lcd.print(«I2C OK ID:»); lcd.print(id,HEX); }

else lcd.print(«I2C ERR»);

// загрузить автосохранённое состояние (если валидно)

autosaveLoadOnBoot();

// аналог ON, применить конфиг в железо

wr(REG_SYS,0x02);

writePathConfig(); setFilter(g_dfilt); applySafe_VolBal();

applyAutoMute(); applyTHD_C2(); applyTHD_C3();

drawMenu();

}

void loop(){

static uint32_t tPoll=0;

static uint32_t tStat=0;

if(millis()-tPoll>5){ pollBtn(); tPoll=millis(); }

int16_t d=enc_delta; enc_delta=0;

// редактирование

if(edit && d){

switch(menu_idx){

// базовые

case 1:{ int n=g_volBase+(d>0?+1:-1); if(n<0)n=0; if(n>255)n=255; g_volBase=n; onChangeSafe(1);}break;

case 2:{ int n=g_balance+(d>0?+1:-1); if(n<-24)n=-24; if(n>24)n=24; g_balance=n; onChangeSafe(1);}break;

case 3:{ int n=g_dfilt +(d>0?+1:-1); if(n<0)n=7; if(n>7)n=0; g_dfilt=n; onChangeSafe(2);}break;

case 4:{ int n=g_path +(d>0?+1:-1); if(n<0)n=3; if(n>3)n=0; g_path =n; onChangeSafe(3);}break;

// bypass

case 5: g_bypIIR = !g_bypIIR; onChangeSafe(3); break;

case 6: g_bypFIR4 = !g_bypFIR4; onChangeSafe(3); break;

case 7: g_bypFIR2 = !g_bypFIR2; onChangeSafe(3); break;

// AutoMute

case 8: g_amCh1 = !g_amCh1; onChangeSafe(4); break;

case 9: g_amCh2 = !g_amCh2; onChangeSafe(4); break;

case 10: g_amRampGND = !g_amRampGND; onChangeSafe(4); break;

case 11:{ int n=g_amTime+(d>0?+1:-1); if(n<0)n=0; if(n>0x07FF)n=0x07FF; g_amTime=(uint16_t)n; onChangeSafe(4);}break;

// THD

case 12:{ int n=g_c2_L+(d>0?+1:-1); if(n<-32768)n=-32768; if(n>32767)n=32767; g_c2_L=(int16_t)n; onChangeSafe(5);}break;

case 13:{ int n=g_c2_R+(d>0?+1:-1); if(n<-32768)n=-32768; if(n>32767)n=32767; g_c2_R=(int16_t)n; onChangeSafe(5);}break;

case 14:{ int n=g_c3_L+(d>0?+1:-1); if(n<-32768)n=-32768; if(n>32767)n=32767; g_c3_L=(int16_t)n; onChangeSafe(6);}break;

case 15:{ int n=g_c3_R+(d>0?+1:-1); if(n<-32768)n=-32768; if(n>32767)n=32767; g_c3_R=(int16_t)n; onChangeSafe(6);}break;

// интерфейс/PLL

case 16:{ int n=g_pol+(d>0?+1:-1); if(n<0)n=3; if(n>3)n=0; g_pol=n; onChangeDanger(10);}break;

case 17:{ int n=g_pll+(d>0?+1:-1); if(n<0x01)n=0x01; if(n>0x10)n=0x10; g_pll=n; onChangeDanger(11);}break;

case 18: g_autoClk=!g_autoClk; onChangeDanger(12); break;

case 19: g_autoIn =!g_autoIn; onChangeDanger(13); break;

// пресеты

case 20:{ int n=g_presetSel+(d>0?+1:-1); if(n<1)n=1; if(n>3)n=3; g_presetSel=n; }break;

case 21:{ int n=g_presetSel+(d>0?+1:-1); if(n<1)n=1; if(n>3)n=3; g_presetSel=n; }break;

case 22: g_autosave=!g_autosave; autosaveWrite(); break;

case 23: g_hard!g_hardOnly; autosaveWrite(); break;

}

drawMenu();

}

// навигация

if(!edit && d){

int n = (int)menu_idx + (d>0?+1:-1);

if(n<0) n=MCNT-1; if(n>=MCNT) n=0;

menu_idx=(uint8_t)n; drawMenu();

}

// клики

if(btn_short){ btn_short=false; if(menu_idx==0) showStatus(); else doAction(menu_idx); }

if(btn_dbl){ btn_dbl=false; if(!g_hardOnly){ pend.softReset=false; runPending(); showStatus(); } }

if(btn_long){ btn_lfalse; edit=!edit; lcd.setCursor(15,0); lcd.print(edit?"*":" "); }

// фон

runPending();

if(menu_idx==0 && millis()-tStat>800){ showStatus(); tStat=millis(); }

}

0
Pushok62 Pushok62 Документация к ES9039Q2M 4 дня назад

Можно на vo_pushkov@mail.ru, а лучше оформить здесь на сайте статьёй, чтобы другие могли воспользоваться этой ценной информацией.

0
Le81 Le81 Документация к ES9039Q2M 4 дня назад

Куда скинуть?

0
Pushok62 Pushok62 Документация к ES9039Q2M 4 дня назад

Спасибо!

+3
Le81 Le81 Документация к ES9039Q2M 4 дня назад

Да конечно, скейч написан под ардуино нано, думаю без труда можно перепесать под свой контролер, сейчас работает с меню, громкость баланс, фазовый захват, полярность сигнала, авто формат, авто вход, настройка стерео и двойное моно, тоесть сам ставишь какой чип будет правый а какой левый, все фильтры, ещё дописал настройки по звуку, но не обкатал их, завтра займусь, короче заставил для эксперемента включить в меню вообще всё что умеет чип, допилю и скину. А так была плата с Китая, там блютуз и два ципа es9039q2m, Китай не стал заморачиватся с двойным моно и просто включил параллельно выходы, на плате был процессор который я так понял только включал в софт es9039q2m, но звук мне не понравился, короче выкинул проц, за одно спалил обе es9039q2m, пока игрался в хард режиме, заказал новый но он больше не запел в плате, скорее всего второго чипа не хватало, проц ждал два адреса от es9039q2m, короче пришлось играться с ардуино, звук на много лучше сейчас чем был с родным проц, сейчас в настройках появилась функция по фильтру гармоник, то есть подавляя вторую или 3 меняет восприятия.

0
Pushok62 Pushok62 Документация к ES9039Q2M 4 дня назад

Подéлитесь описанием конструкции и исходниками?

0
igorigotos17 igorigotos17 Дискретный операционный усилитель AH-OP3 v1.0 4 дня назад

Отличные параметры для дискретного ОУ!

0
Le81 Le81 Документация к ES9039Q2M 5 дней назад

Неделю мучений и чат джипити запустил es9039q2m на ардуино! Строки с пиндоса реально помогли.

0
caleb caleb Pcm58 продам 6 дней назад

Да вообще весьма вкусная плата.

+1
admin admin Переделка модуля XingCore в slave для работы с AH-D16 Pro / AH-D17 Pro 6 дней назад

корпус USB нельзя, он с землей соединяется через емкость, т.е. прямого соединения не имеет.