Управление DSP
- Войдите на сайт для отправки комментариев
Ср, 23/12/2015 - 08:42
Здравствуйте. Может кто подсказать как управлять STA309A, или TAS5508 с arduino? Управление идет по i2C, а вот какие данные отправлять не совсем понятно. Например, для STA309A нужно отправить массив значений только на эквалайзер
Speaker_EQ_Table_48000[] = { {0x00,0x000000},{0x01,0x000000},{0x02,0x000000},{0x03,0x000000},{0x04,0x400000}, // 48KFs, Biquad1, Address: 0x00~0x04 (stability: 0.0000) {0x05,0x000000},{0x06,0x000000},{0x07,0x000000},{0x08,0x000000},{0x09,0x400000}, // 48KFs, Biquad2, Address: 0x05~0x09 (stability: 0.0000) {0x0A,0x000000},{0x0B,0x000000},{0x0C,0x000000},{0x0D,0x000000},{0x0E,0x400000}, // 48KFs, Biquad3, Address: 0x0A~0x0E (stability: 0.0000) {0x0F,0x000000},{0x10,0x000000},{0x11,0x000000},{0x12,0x000000},{0x13,0x400000}, // 48KFs, Biquad4, Address: 0x0F~0x13 (stability: 0.0000) {0x14,0x000000},{0x15,0x000000},{0x16,0x000000},{0x17,0x000000},{0x18,0x400000}, // 48KFs, Biquad5, Address: 0x14~0x18 (stability: 0.0000) {0x19,0x000000},{0x1A,0x000000},{0x1B,0x000000},{0x1C,0x000000},{0x1D,0x400000}, // 48KFs, Biquad6, Address: 0x19~0x1D (stability: 0.0000) {0x1E,0x000000},{0x1F,0x000000},{0x20,0x000000},{0x21,0x000000},{0x22,0x400000}, // 48KFs, Biquad7, Address: 0x1E~0x22 (stability: 0.0000) {0x23,0x000000},{0x24,0x000000},{0x25,0x000000},{0x26,0x000000},{0x27,0x400000}, // 48KFs, Biquad8, Address: 0x23~0x27 (stability: 0.0000) {0x28,0x000000},{0x29,0x000000},{0x2A,0x000000},{0x2B,0x000000},{0x2C,0x400000}, // 48KFs, Biquad9, Address: 0x28~0x2C (stability: 0.0000) {0x2D,0x000000},{0x2E,0x000000},{0x2F,0x000000},{0x30,0x000000},{0x31,0x400000} // 48KFs, Biquad10, Address: 0x2D~0x31 (stability: 0.0000) };
А там параметров намного больше.
А Вы дэйташит на него внимательно изучали?
Даташиты не очень умею читать в части управления, многого не понимаю. Просто есть программа для конфигурирования этих чипов, это из нее.
Так что Вы хотите, чтобы кто-то внимательно изучил дэйташит и пересказал Вам?
Но если Вы не понимаете сам дэйташит, то почему думаете, что сможете понять пересказ?
Не так. Просто я не понимаю, мне все эти массивы слать туда, или как-то проще можно сделать.
Это из даташита громкость, с программной конфигурацией совсем не похожи. Как это понять?
kimmel.dima , как разберетесь, черкните сюда. У меня вопрос какая минимильная инициализация является необходимой для запуска.
У самого мастер кит BA2070 валяется на TAS5504A (+ PL1705 + 2 PCM1808 ) и усилители BA2071 http://lib.chipdip.ru/269/DOC000269591.pdf . Кончилась atmega8 (греется, кз на пине было) , она с кнопок громкости управляла ей. TAS5504A была куплена новая и заменена. Техподдержки на мастер кит нет, прошивки сказали нет (секрет), покупайте новую линейку усилителей. // А зачем , раз такая низкая надёжность и не ремонтопригодность при потраченных 8т.р. ?
Так что единственный вариант починить через arduino .
Схема BA2070 ( BM2070) на TAS5504 к BM2071 http://masterkit.ru/zip/bm2070.pdf
Ок. Примерно представляю, что надо слать, а что конкретно - не знаю.
Подскажите пожалуйста, по таблице из даташита:
Правильная посылка получается?
slider, в этом коде полное управление таской. // TAS5518 and CS8416 User int32_terface for CrossOver / Volume / EQ control // KOON3876 // 2006.12.23 // For Atmel ATMega128 #include <inttypes.h> #include <math.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <avr/eeprom.h> #include <avr/pgmspace.h> #include <util/delay.h> //#include <avr/io.h> //#include <compat/twi.h> #include "lcd.h" #include "i2cmaster.h" //I2C device address of CS8416 #define CS8416_ADDRESS 0x20 //AD0 = 0 //AD1 = 0 //AD2 = 0 //BASE = 0010xxx #define TAS5508_ADDRESS 0x36 // 1/3Oct Equalizer Frequencies const uint16_t EQFreqs[32] = {0,20,25,32,40,50,63,80, 100,125,160,200,250,315,400,500, 630,800,1000,1250,1600,2000,2500,3150, 4000,5000,6300,8000,10000,12500,16000,20000}; // Strings to show const char EQFreqStr[32][8] = {"None","20Hz","25Hz","32Hz", "40Hz","50Hz","63Hz","80Hz", "100Hz","125Hz","160Hz","200Hz", "250Hz","315Hz","400Hz","500Hz", "630Hz","800Hz","1.0kHz","1.25kHz", "1.6kHz","2.0kHz","2.5kHz","3.15kHz", "4.0kHz","5.0kHz","6.3kHz","8.0kHz", "10kHz","12.5kHz","16kHz","20kHz"}; //string for Q each index (actual Q = Q^2/100) const char EQQStr[32][8] = {"0.000","0.010","0.040","0.090", "0.160","0.250","0.360","0.490", "0.640","0.810","1.000","1.210", "1.440","1.690","1.960","2.250", "2.560","2.890","3.240","3.610", "4.000","4.410","4.840","5.290", "5.760","6.250","6.760","7.290", "7.840","8.410","9.000","9.610"}; const char EQTypeStr[4][12] = {"None","LowShelf","HighShelf","Peaking"}; // Crossover Filter Point32_ts const uint16_t FilterFreqs[32] = {0,50,65,80,100,120,150,180,220,260,300,350, 400,500,650,800,1000,1200,1500,1800,2200,2600,3000, 3500,4000,5000,6500,8000,10000,12000,15000,18000}; const char FilterFreqStr[32][8] = {"None","50Hz","65Hz","80Hz", "100Hz","120Hz","150Hz","180Hz", "220Hz","260Hz","300Hz","350Hz", "400Hz","500Hz","650Hz","800Hz", "1kHz","1.2kHz","1.5kHz","1.8kHz", "2.2kHz","2.6kHz","3.0kHz","3.5kHz", "4.0kHz","5.0kHz","6.5kHz","8.0kHz", "10kHz","12kHz","15kHz","18kHz"}; // CS8416 SPDIF Frequencies const uint32_t SPDIFFreqs[4] = {44100,48000,88200,96000}; const char currentfsstr[4][8] = {"44.1kHz","48kHz","88.2kHz","96kHz"}; // Global Values uint8_t currentfs; //Fs (44.1/48/88.2/96) current state uint8_t currentFilterMenu; //Filter Menu Number uint8_t FilterChanged; //1: There were data change uint8_t currentEQMenu; //EQ Menu Number uint8_t EQChanged; //1: there were data change uint8_t KeyMode; //0:none, 1: First Key, 2: Repeat Key uint8_t PrevKey; //remember previous key state uint8_t NewKey; //get new key entry // Parameters to store Flash struct EQParam { uint8_t EQType; //0:None, 1:LowShelf, 2:HighShelf, 3:Peaking uint8_t EQFreq; //0 - 31 uint8_t EQQ; //0 - 31 int8_t EQGain; //-15,... 0,... 15 }; //4 bytes struct FilterParam { uint8_t LPF; // 0:No LPF uint8_t HPF; //0:No HPF int8_t OFFSET; //0:mid uint8_t MUTE; //0:normal, 1:mute }; //4 bytes struct Params { int16_t currentvol; int8_t currentch; int8_t currentwin; struct FilterParam FilterParams[4]; //CH12,34,56,78 struct EQParam EQParams[4][3]; // CH12,34,56,78 - EQ5,6,7 } ; struct Params DevParam; //4 + 16 + 48 = 68 bytes struct Params DevParam_EEPROM __attribute__((section(".eeprom"))); //Utility Functions void msDelay(uint16_t delay) { while (delay--) { _delay_ms(1); } } //Read Flash void readDevParam() { eeprom_busy_wait(); eeprom_read_block(&DevParam, &DevParam_EEPROM,sizeof(DevParam_EEPROM)); } //Write Flash void writeDevParam(int mode) { eeprom_busy_wait(); switch (mode) { case 0: //Write All eeprom_write_block(&DevParam, &DevParam_EEPROM, sizeof(DevParam_EEPROM)); break; case 1: //Volume Only eeprom_write_word(&(DevParam_EEPROM.currentvol), DevParam.currentvol); break; case 2: //Channel Only eeprom_write_byte(&(DevParam_EEPROM.currentch), DevParam.currentch); break; default: eeprom_write_block(&DevParam, &DevParam_EEPROM, sizeof(DevParam_EEPROM)); break; } eeprom_busy_wait(); } //LCD Functions //LCD Function, String 0 terminated SendStr, Line is Upper(1) Lower(2) void SendString(char * SendStr, uint8_t Line) { int StrLen; unsigned char Packet[32]; int i; lcd_gotoxy(0,0); msDelay(1); if (Line == 2) { lcd_gotoxy(0,1); } msDelay(1); StrLen = strlen(SendStr); memset(Packet, 0, sizeof(Packet)); strncpy(Packet, SendStr, 16); for (i = StrLen; i <= 18; i++) { Packet[i] = 0x20; } lcd_puts(Packet); lcd_gotoxy(0,0); } //LCD Function void ClearLCD() { lcd_clrscr(); } //LCD Function uint8_t PollKey() { if ( bit_is_clear(PINA, PINA0)) return 3; if ( bit_is_clear(PINA, PINA4)) return 4; if ( bit_is_clear(PINA, PINA1)) return 5; if ( bit_is_clear(PINA, PINA3)) return 6; if ( bit_is_clear(PINA, PINA2)) return 1; /* return 1; //ENTER return 2; //cancel return 3; //up return 4; //Down return 5; //Left return 6; //right */ return 0; } //I2C Function /* I2CWrite write data to slave. Sends START, slave address, index and then data, STOP Waits for slave to respond. PARAM1: uint8_t address - slave device address PARAM2: uint8_t index - subaddress of register/memory to write PARAM3: char * writestring - write data buffer PARAM4: uint8_t len - length of data to write RETURN: 0 or negative error code (see code) */ int8_t I2CWrite(uint8_t address, uint8_t subaddress, char * writestring, uint8_t len) { uint8_t cnt; int8_t err; i2c_start(address + I2C_WRITE); err = i2c_write(subaddress); if (err == 1) { i2c_stop(); return -20; // write failed } for (cnt = 0; cnt < len; cnt++) { i2c_write(writestring[cnt]); } i2c_stop(); return 0; } /* I2CRead PARAM1: uint8_taddress - slave address PARAM2: uint8_t subaddress - subaddress in in EEPROM to read from PARAM3: char *retstring - buffer for data PARAM4: uint8_t len - size of data buffer RETURN: 0 or error code*/ int8_t I2CRead(uint8_t address, uint8_t subaddress, char * retstring, uint8_t len) { uint8_t cnt; int8_t err; i2c_start(address + I2C_WRITE); err = i2c_write(subaddress); if (err == 1) { i2c_stop(); return -20; // access failed } i2c_rep_start(address + I2C_READ); for (cnt = 0; cnt < len; cnt++) { if (cnt==(len-1)) { retstring[cnt] = i2c_readNak(); //nak } else { retstring[cnt] = i2c_readAck(); } } i2c_stop(); return 0; } //I2C Functions uint8_t I2C_GetFs() { //returns data rate. // 0 : Error // 1 : invalid // 2 : 32 kHz // 3 : 38 kHz // 4 : 44.1kHz // 5 : 48 kHz // 6 : 88.2 kHz // 7 : 96 kHz // 8 : 176.4kHz // 9 : 192 kHz char Clk_Mode; uint8_t return_code; return_code = I2CRead(TAS5508_ADDRESS, 0x00, &Clk_Mode, 1); if (return_code != 0) { return 0; } //if ( (Clk_Mode & 0x01) == 0){ return 1; } //upper 3 bit shows mode return ( ((Clk_Mode & 0xE0) >> 5) + 2 ); } // TAS5518 and PSVC Volume control // PSVC is 4 bit programmable, 16dB void I2C_SetVolume() { char test_string[4]; uint8_t return_code; int16_t TAS5508Volume; uint8_t PortAVolume; if (DevParam.currentvol < 0x48) //+x.xx dB { TAS5508Volume = DevParam.currentvol; PortAVolume = 0x0F; } else { if (DevParam.currentvol < 0x89) //0 - -15dB { TAS5508Volume = 0x48; PortAVolume = 16 - (uint8_t)(((DevParam.currentvol - 0x48)) / 4); } else { TAS5508Volume = DevParam.currentvol - 0x48; PortAVolume = 0; } } //set volume test_string[0] = 0; test_string[1] = 0; test_string[2] = 0; test_string[3] = TAS5508Volume & 0xff; return_code = I2CWrite(TAS5508_ADDRESS, 0xD9, test_string, 4); //WrPortI(PADR, &PADRShadow, PortAVolume); //Output Volume to Control PORTB = (PortAVolume)<<4; } // CS8416 Rx Selector void I2C_SetCH() { uint8_t WriteData; WriteData = 0x80 + DevParam.currentch * 8 + DevParam.currentch; I2CWrite(CS8416_ADDRESS, 0x04, &WriteData, 1); } //Make biquad Filter parameter void MakeEQ(int32_t Fs, int32_t f0, int32_t mode, double Q, int32_t gain, uint8_t * EQ) { double w0; double cosw0; double sinw0; double alpha; double A; double sqrtA; double twosqrtAalpha; double b0; double b1; double b2; double a0; double a1; double a2; int32_t Qb0; int32_t Qb1; int32_t Qb2; int32_t Qa1; int32_t Qa2; b0 = 0.0; b1 = 1.0; b2 = 0.0; a0 = 1.0; a1 = 0.0; a2 = 0.0; w0 = 2.000 * 3.141516 * f0 / Fs; cosw0 = cos(w0); sinw0 = sin(w0); alpha = sinw0 / (2.00 * Q); A = pow( ((double)(gain)) /40.0 , 10); sqrtA = sqrt(A); twosqrtAalpha = 2*sqrtA*alpha; if ( mode == 0) //HPF { a0 = 1.0 + alpha; b1 = -1.0 * (1.0 + cosw0) / a0 ; b0 = -1.0 * b1 / 2.00; b2 = b0; a1 = -2.0 * cosw0 / a0 ; a2 = (1.0 - alpha) / a0; } if ( mode == 1) //LPF { a0 = 1.0 + alpha; b1 = (1.0 - cosw0) / a0 ; b0 = b1 / 2.00; b2 = b0; a1 = -2.0 * cosw0 / a0 ; a2 = (1.0 - alpha) / a0; } if ( mode == 2) //LowShelf { a0 = (A+1)+(A-1)*cosw0+twosqrtAalpha; b0 = A*((A+1) - (A-1)*cosw0 + twosqrtAalpha); b1 = 2*A*((A-1) - (A+1)*cosw0) ; b2 = A*((A+1)-(A-1)*cosw0-twosqrtAalpha); a1 = -2.0*((A-1)+(A+1)*cosw0) ; a2 = (A+1)+(A-1)*cosw0-twosqrtAalpha; } if ( mode == 3) //HighShelf { a0 = (A+1)-(A-1)*cosw0+twosqrtAalpha; b0 = A*((A+1) + (A-1)*cosw0 + twosqrtAalpha); b1 = -2*A*((A-1) + (A+1)*cosw0) ; b2 = A*((A+1)+(A-1)*cosw0-twosqrtAalpha); a1 = 2.0*((A-1)-(A+1)*cosw0) ; a2 = (A+1)-(A-1)*cosw0-twosqrtAalpha; } if ( mode == 4) //Peaking { a0 = 1.0 + alpha / A; b0 = 1.0 + alpha * A; b1 = -2.0 * cosw0 ; b2 = 1.0 - alpha * A; a1 = -2.0 * cosw0 ; a2 = 1.0 - alpha / A; } if ( mode > 1) { b0 = b0 / a0; b1 = b1 / a0; b2 = b2 / a0; a1 = a1 / a0; a2 = a2 / a0; } //quantize Qb0 = (int32_t)(b0 * 8388608L); Qb1 = (int32_t)(b1 * 8388608L); Qb2 = (int32_t)(b2 * 8388608L); Qa1 = (int32_t)(a1 * -8388608L); Qa2 = (int32_t)(a2 * -8388608L); //Modify sign bit if (Qb0 < 0) Qb0 = Qb0 + 268435456L; if (Qb1 < 0) Qb1 = Qb1 + 268435456L; if (Qb2 < 0) Qb2 = Qb2 + 268435456L; if (Qa1 < 0) Qa1 = Qa1 + 268435456L; if (Qa2 < 0) Qa2 = Qa2 + 268435456L; //get each byte *(EQ ) = (uint8_t)((Qb0>>24) & 0xFF); *(EQ+1 ) = (uint8_t)((Qb0>>16) & 0xFF); *(EQ+2 ) = (uint8_t)((Qb0>>8) & 0xFF); *(EQ+3 ) = (uint8_t)( Qb0 & 0xFF); *(EQ+4 ) = (uint8_t)((Qb1>>24) & 0xFF); *(EQ+5 ) = (uint8_t)((Qb1>>16) & 0xFF); *(EQ+6 ) = (uint8_t)((Qb1>>8) & 0xFF); *(EQ+7 ) = (uint8_t)( Qb1 & 0xFF); *(EQ+8 ) = (uint8_t)((Qb2>>24) & 0xFF); *(EQ+9 ) = (uint8_t)((Qb2>>16) & 0xFF); *(EQ+10) = (uint8_t)((Qb2>>8) & 0xFF); *(EQ+11) = (uint8_t)( Qb2 & 0xFF); *(EQ+12) = (uint8_t)((Qa1>>24) & 0xFF); *(EQ+13) = (uint8_t)((Qa1>>16) & 0xFF); *(EQ+14) = (uint8_t)((Qa1>>8) & 0xFF); *(EQ+15) = (uint8_t)( Qa1 & 0xFF); *(EQ+16) = (uint8_t)((Qa2>>24) & 0xFF); *(EQ+17) = (uint8_t)((Qa2>>16) & 0xFF); *(EQ+18) = (uint8_t)((Qa2>>8) & 0xFF); *(EQ+19) = (uint8_t)( Qa2 & 0xFF); } void ClearEQ(uint8_t * EQ) { //get each byte memset(EQ, 0,20); *(EQ+1 ) = 0x80; } // convert Q value to string double EQQNumToValue(int32_t EQQ) { double retVal; if ((EQQ < 0) || (EQQ > 31)) { retVal = 0; } else { retVal = (EQQ * EQQ) / 100.00 ; } return retVal; } // convert EQ frequency value to string int32_t FreqFromEQSetting(int32_t EQSetting) { if ((EQSetting < 0) || (EQSetting > 31)) return 0; return EQFreqs[EQSetting]; } // convert Filter frequency value to string int32_t FreqFromFilterSetting(int32_t FilterSetting) { if ((FilterSetting < 0) || (FilterSetting > 31)) return 0; return FilterFreqs[FilterSetting]; } // Calculate Equalizers and apply void applyEQ(int32_t FS) { uint8_t EQ[20]; int32_t return_code; int32_t Freq; double Q; int32_t i; int32_t j; //Loop for CH12,34,56,78 for (j = 0; j <= 3; j++) { //Loop for EQ5,6,7 in each CH for (i = 0; i <= 2; i++) { Freq = FreqFromEQSetting(DevParam.EQParams[j][i].EQFreq); if ((Freq > 0) && (DevParam.EQParams[j][i].EQType > 0)) { Q = EQQNumToValue(DevParam.EQParams[j][i].EQQ); MakeEQ(FS, Freq, DevParam.EQParams[j][i].EQType + 1, Q , DevParam.EQParams[j][i].EQGain, EQ); } else { ClearEQ(EQ); } return_code = I2CWrite(TAS5508_ADDRESS, 0x55 + i + j*7*2,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x5C + i + j*7*2,EQ,20); } } } // Calculate Filter and apply void applyfilter(int32_t FS) { uint8_t EQ[20]; int32_t return_code; int32_t Freq; uint8_t Param[4]; uint8_t MutePattern; int32_t i; for (i = 0; i <= 3; i++) { //CHxx EQ1,2 (LPF) Freq = FreqFromFilterSetting(DevParam.FilterParams[i].LPF); if (Freq > 0) { MakeEQ(FS, Freq, 1, 0.71, 0, EQ); //Q=0.71 LPF } else { ClearEQ(EQ); } return_code = I2CWrite(TAS5508_ADDRESS, 0x51+i*14,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x52+i*14,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x58+i*14,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x59+i*14,EQ,20); //CHxx EQ3,4 (HPF) Freq = FreqFromFilterSetting(DevParam.FilterParams[i].HPF); if (Freq > 0) { MakeEQ(FS, Freq, 0, 0.71, 0, EQ); //Q=0.71, HPF } else { ClearEQ(EQ); } return_code = I2CWrite(TAS5508_ADDRESS, 0x53+i*14,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x54+i*14,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x5A+i*14,EQ,20); return_code = I2CWrite(TAS5508_ADDRESS, 0x5B+i*14,EQ,20); } Param[0] = 0; Param[1] = 0; Param[2] = 0; for (i = 0; i <= 3; i++) { //CH Offset Param[3] = (uint8_t)(0x48 - DevParam.FilterParams[i].OFFSET * 4); return_code = I2CWrite(TAS5508_ADDRESS, 0xD1+i*2,Param,4); return_code = I2CWrite(TAS5508_ADDRESS, 0xD2+i*2,Param,4); } //CH Mute MutePattern = (uint8_t) (DevParam.FilterParams[0].MUTE * 0x03 + DevParam.FilterParams[1].MUTE * 0x0C + DevParam.FilterParams[2].MUTE * 0x30 + DevParam.FilterParams[3].MUTE * 0xC0); return_code = I2CWrite(TAS5508_ADDRESS, 0x0F, &MutePattern,1); } //Filter setting entry void Menu01(int32_t NewKeyData) { char Line1[20]; char Line2[20]; switch (NewKeyData) { case 1: //Enter case 4: //Down currentFilterMenu = 0; FilterChanged = 0; DevParam.currentwin = 3; return; break; case 2: //Cancel case 3: //Up DevParam.currentwin = 0; return; break; case 5: //Left case 6: //Right DevParam.currentwin = 2; return; break; default: break; } //Create Screen String sprintf(Line1, "KDA-TAS4i"); sprintf(Line2, "Filter Menu ?"); //Send LCD SendString(Line1,1); SendString(Line2,2); } //EQ Setting Entry void Menu02(int32_t NewKeyData) { char Line1[20]; char Line2[20]; switch (NewKeyData) { case 1: //Enter case 4: //Down currentEQMenu = 0; EQChanged = 0; DevParam.currentwin = 4; return; break; case 2: //cancel case 3: //Up DevParam.currentwin = 0; return; break; case 5: //Left case 6: //Right DevParam.currentwin = 1; return; break; default: break; } //Create Screen String sprintf(Line1, "KDA-TAS4i"); sprintf(Line2, "EQ Menu ?"); //Send LCD SendString(Line1,1); SendString(Line2,2); } // Convert Filter value to string void FilterNumToStr(int32_t FilterNum, char * FilterStr) { if ((FilterNum < 0) || (FilterNum > 31)) strcpy(FilterStr, "--"); else strcpy(FilterStr, FilterFreqStr[FilterNum]); } void MuteToStr(int32_t MuteValue, char * MuteStr) { if (MuteValue == 0) { strcpy(MuteStr, "In Use"); } else { strcpy(MuteStr, "Mute"); } } //Filter Menu Screen void FilterMenu(int32_t NewKeyData) { //Control EQ0,1(reserved for LPF) ,2,3 (for HPF) char Line1[20]; char Line2[20]; int32_t CurrentCH; int32_t CurrentFilterSetting; CurrentCH = (int32_t)(currentFilterMenu / 4); CurrentFilterSetting = currentFilterMenu - CurrentCH * 4; switch (NewKeyData) { case 1: //Enter //save changes FilterChanged = 0; DevParam.currentwin = 3; applyfilter(SPDIFFreqs[currentfs - 4]); writeDevParam(0); return; break; case 2: //Cancel //discard changes FilterChanged = 0; readDevParam(); DevParam.currentwin = 1; writeDevParam(0); return; break; case 3: //Up if (currentFilterMenu > 0) currentFilterMenu -= 1; else { if (currentFilterMenu == 0) { DevParam.currentwin = 1; return; } } break; case 4: //Down if (currentFilterMenu < 15) currentFilterMenu += 1; else currentFilterMenu = 15; break; case 5: //Left FilterChanged = 1; switch (CurrentFilterSetting) { case 0: //LPF if (DevParam.FilterParams[CurrentCH].LPF > 0) DevParam.FilterParams[CurrentCH].LPF -= 1; else DevParam.FilterParams[CurrentCH].LPF = 0; break; case 1: //HPF if (DevParam.FilterParams[CurrentCH].HPF > 0) DevParam.FilterParams[CurrentCH].HPF -= 1; else DevParam.FilterParams[CurrentCH].HPF = 0; break; case 2: //OFFSET if (DevParam.FilterParams[CurrentCH].OFFSET > -15) DevParam.FilterParams[CurrentCH].OFFSET -= 1; else DevParam.FilterParams[CurrentCH].OFFSET = -15; break; case 3: //MUTE if (DevParam.FilterParams[CurrentCH].MUTE == 1) DevParam.FilterParams[CurrentCH].MUTE = 0; else DevParam.FilterParams[CurrentCH].MUTE = 1; break; } break; case 6: //Right FilterChanged = 1; switch (CurrentFilterSetting) { case 0: //LPF if (DevParam.FilterParams[CurrentCH].LPF < 31) DevParam.FilterParams[CurrentCH].LPF += 1; else DevParam.FilterParams[CurrentCH].LPF = 31; break; case 1: //HPF if (DevParam.FilterParams[CurrentCH].HPF < 31) DevParam.FilterParams[CurrentCH].HPF += 1; else DevParam.FilterParams[CurrentCH].HPF = 0; break; case 2: //OFFSET if (DevParam.FilterParams[CurrentCH].OFFSET < 15) DevParam.FilterParams[CurrentCH].OFFSET += 1; else DevParam.FilterParams[CurrentCH].OFFSET = 15; break; case 3: //MUTE if (DevParam.FilterParams[CurrentCH].MUTE == 0) DevParam.FilterParams[CurrentCH].MUTE = 1; else DevParam.FilterParams[CurrentCH].MUTE = 0; break; } break; default: //SendString("No Key",2); break; } //Create Screen String switch (CurrentFilterSetting) { case 0: //LPF sprintf(Line1, "CH%i-%i LPF",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2); FilterNumToStr(DevParam.FilterParams[CurrentCH].LPF,Line2); break; case 1: //HPF sprintf(Line1, "CH%i-%i HPF",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2); FilterNumToStr(DevParam.FilterParams[CurrentCH].HPF,Line2); break; case 2: //OFFSET sprintf(Line1, "CH%i-%i OFFSET",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2); sprintf(Line2, "%ddB", DevParam.FilterParams[CurrentCH].OFFSET); break; case 3: //MUTE sprintf(Line1, "CH%i-%i MUTE",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2); MuteToStr(DevParam.FilterParams[CurrentCH].MUTE, Line2); break; } //Send LCD if (FilterChanged == 1) { strcat(Line1, " *"); } SendString(Line1,1); SendString(Line2,2); } void EQTypeToStr(int32_t EQTypeNum, char * RetStr) { if ((EQTypeNum < 0) || (EQTypeNum > 3)) strcpy(RetStr, "--"); else strcpy(RetStr, EQTypeStr[EQTypeNum]); } void EQFreqNumToStr(int32_t EQFreqNum, char * EQFreqRetStr) { if ((EQFreqNum < 0) || (EQFreqNum > 31)) strcpy(EQFreqRetStr, "--"); else strcpy(EQFreqRetStr, EQFreqStr[EQFreqNum]); } void EQQNumToStr(int32_t EQQNum, char * EQQRetStr) { if ((EQQNum < 0) || (EQQNum > 31)) strcpy(EQQRetStr, "--"); else strcpy(EQQRetStr, EQQStr[EQQNum]); } //EQ Menu Screen void EQMenu(int32_t NewKeyData) { //Control EQ5,6,7 char Line1[20]; char Line2[20]; //double EQQ; int32_t CurrentCH; //0,1,2,3 = CH12,34,56,78 int32_t CurrentEQ; //0,1,2 = EQ5,6,7 int32_t CurrentSetting; //0,1,2,3 = EQType, EQFreq, EQQ, EQGain CurrentCH = (int32_t)(currentEQMenu / 12); CurrentEQ = (int32_t)((currentEQMenu - CurrentCH * 12) / 4); CurrentSetting = currentEQMenu - CurrentCH * 12 - CurrentEQ * 4; switch (NewKeyData) { case 1: //Enter //save changes EQChanged = 0; DevParam.currentwin = 4; applyEQ(SPDIFFreqs[currentfs - 4]); writeDevParam(0); return; break; case 2: //Cancel //discard changes EQChanged = 0; readDevParam(); DevParam.currentwin = 2; writeDevParam(0); return; break; case 3: //Up if (currentEQMenu > 0) currentEQMenu -= 1; else { if (currentEQMenu == 0) { DevParam.currentwin = 2; return; } } break; case 4: //Down if (currentEQMenu < 47) currentEQMenu += 1; else currentEQMenu = 47; break; case 5: //Left EQChanged = 1; switch (CurrentSetting) { case 0: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQType > 0 ) //0:None, 1:LowShelf, 2:HighShelf, 3:Peaking DevParam.EQParams[CurrentCH][CurrentEQ].EQType -= 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQType = 0; break; case 1: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq > 0 ) //0 - 31 DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq -= 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq = 0; break; case 2: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQQ > 0 ) //0 - 31 DevParam.EQParams[CurrentCH][CurrentEQ].EQQ -= 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQQ = 0; break; case 3: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQGain > -15 ) //-15,... 0,... 15 DevParam.EQParams[CurrentCH][CurrentEQ].EQGain -= 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQGain = -15; break; default: break; } break; case 6: //Right EQChanged = 1; switch (CurrentSetting) { case 0: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQType < 3 ) //0:None, 1:LowShelf, 2:HighShelf, 3:Peaking DevParam.EQParams[CurrentCH][CurrentEQ].EQType += 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQType = 3; break; case 1: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq < 31 ) //0 - 31 DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq += 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq = 31; break; case 2: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQQ < 31 ) //0 - 31 DevParam.EQParams[CurrentCH][CurrentEQ].EQQ += 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQQ = 31; break; case 3: if ( DevParam.EQParams[CurrentCH][CurrentEQ].EQGain < 15 ) //-15,... 0,... 15 DevParam.EQParams[CurrentCH][CurrentEQ].EQGain += 1; else DevParam.EQParams[CurrentCH][CurrentEQ].EQGain = 15; break; default: break; } break; default: //SendString("No Key",2); break; } //Create Screen String switch (CurrentSetting) { case 0: //EQType sprintf(Line1, "CH%d-%d EQ%d Type",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2,(int8_t)CurrentEQ+5 ); EQTypeToStr(DevParam.EQParams[CurrentCH][CurrentEQ].EQType ,Line2); break; case 1: //EQFreq sprintf(Line1, "CH%d-%d EQ%d Freq",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2,(int8_t)CurrentEQ+5); EQFreqNumToStr(DevParam.EQParams[CurrentCH][CurrentEQ].EQFreq, Line2); break; case 2: //EQQ sprintf(Line1, "CH%d-%d EQ%d Q",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2,(int8_t)CurrentEQ+5); EQQNumToStr(DevParam.EQParams[CurrentCH][CurrentEQ].EQQ, Line2); break; case 3: sprintf(Line1, "CH%d-%d EQ%d Gain",(int8_t)CurrentCH*2+1,(int8_t)CurrentCH*2+2,(int8_t)CurrentEQ+5); sprintf(Line2, "%ddB", DevParam.EQParams[CurrentCH][CurrentEQ].EQGain); break; default: break; } //Send LCD if (EQChanged == 1) { strcat(Line1, " *"); } SendString(Line1,1); SendString(Line2,2); } // Main Screen to show Volume, Channel void mainScreen(int32_t NewKeyData) { char Line1[20]; char Line2[20]; int32_t Volume; Volume = (int32_t)(((DevParam.currentvol - 0x48) * -1) / 4); switch (NewKeyData) { case 1: //Enter //SendString("Enter Pressed",2); DevParam.currentwin = 1; writeDevParam(0); return; break; case 2: //SendString("Cancel Pressed",2); break; case 3: //Up if (Volume < 16) { Volume += 1; DevParam.currentvol = ((Volume * 4) * -1) + 0x48; writeDevParam(1); I2C_SetVolume(); } else Volume = 16; break; case 4: //Down if (Volume > -100) { Volume -= 1; DevParam.currentvol = ((Volume * 4) * -1) + 0x48; writeDevParam(1); I2C_SetVolume(); } else Volume = -100; break; case 5: //Left if (DevParam.currentch > 0) { DevParam.currentch -= 1; writeDevParam(2); I2C_SetCH(); } else DevParam.currentch = 0; break; case 6: //Right if (DevParam.currentch < 7) { DevParam.currentch += 1; writeDevParam(2); I2C_SetCH(); } else DevParam.currentch = 7; break; default: break; } //Create Screen String sprintf(Line1, "KDA-TAS4i D%d", DevParam.currentch); if ((currentfs < 4) || (currentfs > 7)) sprintf(Line2, "%3ddB Fs=--kHz", (int16_t)Volume); else sprintf(Line2, "%3ddB Fs=%s", (int16_t)Volume, currentfsstr[currentfs - 4]); //Send LCD SendString(Line1,1); SendString(Line2,2); } // Get Key / pass screen void ProcessKey(int32_t NewKeyData) { switch (DevParam.currentwin) { case 0: mainScreen(NewKeyData); break; case 1: Menu01(NewKeyData); break; case 2: Menu02(NewKeyData); break; case 3: FilterMenu(NewKeyData); break; case 4: EQMenu(NewKeyData); break; default: mainScreen(NewKeyData); break; } } // Init void initializeBoard() { uint8_t WriteData; char LCDLine[20]; PORTC=0x00; DDRC=0xF7; DDRA = 0xE0; //PortA, 7,6,5 is out, other in PORTA = 0xBF; //LED Off DDRE=0xFF; //PE is output PORTE = 0xC8; //Reset High msDelay(10); DDRB = 0xF0; //PB7,6,5,4 is output PORTB = 0x00; //Set Voltage Lowest lcd_init(LCD_DISP_ON); lcd_home(); i2c_init(); currentfs = 0; //Initialize key state KeyMode = 0; PrevKey = 0; NewKey = 0; readDevParam(); //Once for Initial. //memset(&DevParam, 0, sizeof(DevParam)); ClearLCD(); memset(LCDLine, 0, sizeof(LCDLine)); sprintf(LCDLine, "KOON DIGITAL"); SendString(LCDLine,1); sprintf(LCDLine, " AUDIO DIY"); SendString(LCDLine,2); msDelay(1500); //Serial Audio Format = 1 0 00 0 1 0 1 (I2S 24bit) WriteData = 0x85; //I2S I2CWrite(CS8416_ADDRESS, 0x05, &WriteData, 1); //Control3 = 10110000 WriteData = 0xB0; //1011 GPIO is TX passthrough I2CWrite(CS8416_ADDRESS, 0x03, &WriteData, 1); I2C_SetCH(); //set volume I2C_SetVolume(); ClearLCD(); } // Main Loop int main() { int32_t return_code; int32_t newfs; uint8_t MUTEMode; msDelay(100); initializeBoard(); //set mute pattern MUTEMode = 0x00; //Unmute all return_code = I2CWrite(TAS5508_ADDRESS, 0x0F, &MUTEMode, 1); while (1) { switch(KeyMode) { case 0: msDelay(50); break; case 1: msDelay(400); break; case 2: msDelay(200); break; default: msDelay(100); break; } { //task for check fs newfs = I2C_GetFs(); if (currentfs != newfs) { if ((newfs < 4) || (newfs > 7)) //non support { //mute all MUTEMode = 0xFF; I2CWrite(TAS5508_ADDRESS, 0x0f, &MUTEMode, 1); } else { applyfilter(SPDIFFreqs[newfs-4]); applyEQ(SPDIFFreqs[newfs-4]); } currentfs = newfs; } } //Task Key Process { NewKey = PollKey(); switch(KeyMode) { case 0: //Initial Key State, None Key detected if (NewKey > 0) { KeyMode = 1; //to state 1. if (NewKey != PrevKey) { ProcessKey(NewKey); } PrevKey = NewKey; } else { ProcessKey(0); } break; case 1: //Some key detected. wait 400 ms to another input. if (NewKey > 0) { if (NewKey != PrevKey) { KeyMode = 1; } //different key detected. else { KeyMode = 2; } //Same key detected. ProcessKey(NewKey); PrevKey = NewKey; } else //no key pressed. return to state 0. { KeyMode = 0; PrevKey = NewKey; ProcessKey(0); } break; case 2: //If same key still pressed, run same routine per 100ms. if (NewKey > 0) { if (NewKey != PrevKey) { KeyMode = 1; } //different key detected. else { KeyMode = 2; } //repeat same key operation ProcessKey(NewKey); PrevKey = NewKey; } else { KeyMode = 0; PrevKey = NewKey; ProcessKey(0); } break; default: break; } //switch } //Task } //While return 0; }
ну сами подумайте, кто будет ковыряться в чужом код на 1400 строк...
А Вы дэйташит на него внимательно изучали?
Не умею даташиты читать....
повторю. Hi андриано .
Начните с букваря.
ну сами подумайте, кто будет ковыряться в чужом код на 1400 строк...
Это не мне. Человек попросил какую-нибудь информацию по управлению tas, я скинул (мне не жалко).
А Вы дэйташит на него внимательно изучали?
Не умею даташиты читать....
повторю. Hi андриано .
Начните с букваря.
В каком месте написал, что не умею???
По делу есть что сказать?
Нашел код для sta308. Сама микросхема пока едет, проверить в железе не могу. Посмотрите знающие люди, ошибок много?
И sta308.h
kimmel.dima , как разберетесь, черкните сюда. У меня вопрос какая минимильная инициализация является необходимой для запуска.
У самого мастер кит BA2070 валяется на TAS5504A (+ PL1705 + 2 PCM1808 ) и усилители BA2071 http://lib.chipdip.ru/269/DOC000269591.pdf . Кончилась atmega8 (греется, кз на пине было) , она с кнопок громкости управляла ей. TAS5504A была куплена новая и заменена. Техподдержки на мастер кит нет, прошивки сказали нет (секрет), покупайте новую линейку усилителей. // А зачем , раз такая низкая надёжность и не ремонтопригодность при потраченных 8т.р. ?
Так что единственный вариант починить через arduino .
Схема BA2070 ( BM2070) на TAS5504 к BM2071 http://masterkit.ru/zip/bm2070.pdf
Также хочу разобраться как управлять этим набором.
Пишите в личку , может совместно осилим
Разобрался с TAS5504. TAS5508 аналогична по структуре и управлению. Есть некоторые особенности , плюс 8 выходов.
Сделал управление через ВЕБ интерфейс.
Делал сразу на 8 входных каналов , хотя плату сделал пока на 4 канала.
Не нашел как загрузить изображение
Разобрался с TAS5504. TAS5508 аналогична по структуре и управлению. Есть некоторые особенности , плюс 8 выходов.
Сделал управление через ВЕБ интерфейс.
Делал сразу на 8 входных каналов , хотя плату сделал пока на 4 канала.
Не нашел как загрузить изображение
А код посмотреть можно? У меня полнотью управляется 08-ая, но с дисплеем пока заморочки.
Код написагн для PIC18
Вам врядли подойдет
Допилил код для tas5508. В протеусе все работает.
Люди, скиньте кто-нибудь программу конфигурации пожалуйста, очень надо!!!! Весь интернет облазил и не нашел! Просто отдали плату усилителя от ресивера, там как раз TAS5508.