PT2258 — 6-и канальный регулятор громкости (2) (Arduino)

Ранее в http://rcl-radio.ru/?p=80541 рассматривался пример создания регулятора громкости на аудиопроцессоре PT2258 с использованием четырех разрядного семисегментного индикатора. На этой странице аналогичный проект, но в нем будет использован индикатор LCD2004 c модулем I2C.

ИМС PT2258 — шести канальный регулятор громкости с микроконтроллерным управлением. Управление PT2258 осуществляется при помощи шины I2C. Регулятор громкости обладает низким уровнем шума и малым коэффициентом нелинейных искажений. Регулировка громкости может быть как независимая для каждого канала, так и общая для всех каналов.

Основные характеристики PT2258:

  • Напряжение питания от 5 до 10 В, 9 В — рекомендуемое
  • Ток потребления 8 мА
  • Входное сопротивление 30 кОм
  • Максимальное входное напряжение 2,8 Vrms
  • Разделение каналов 100 дБ
  • Коэффициент нелинейных искажений 0,005%
  • Диапазон регулировки громкости от -79 до 0 дБ
  • Шаг регулировки громкости 1 дБ
  • Режим MUTE
  • Отношение сигнал/шум 105 дБ

Схема регулятора громкости достаточно проста, выводы 4 и 17 (CODE2 и CODE1) в зависимости от подключения к GND или VCC позволяют изменять адрес микросхемы при работе с I2C шиной, что дает возможность подключения других утс-в на шину I2С, у которых нет возможности изменить адрес:

  • CODE1 = GND, CODE2 = GND 80H
  • CODE1 = GND, CODE2 = VCC 84H
  • CODE1 = VCC, CODE2 = GND 88H
  • CODE1 = VCC, CODE2 = VCC 8CH

Библиотека PT2258  поддерживает адрес 0х88, если возникнет необходимость изменить адрес шины I2C, то потребуется корректировка адреса в библиотеке:

Файл — PT2258.h

В платформе Arduino адрес I2C 7 бит, поэтому вместо 0х88 (0B10001000), указывается 0х44 (0B1000100).

Регулятор громкости на PT2258 содержит следующие компоненты:

  • Плата Arduino Nano
  • Дисплей LCD2004 с модулем I2C
  • Часы реального времени DS3231
  • Энкодер KY-040
  • Три тактовые кнопки
  • ИК-датчик VS1838B

Схема регулятора громкости

Основные функциональные возможности регулятора громкости:

  • Основное меню:
    • Регулировка громкости 64 уровня (64 дБ), осуществляется при помощи энкодера и ИК пульта
    • Вывод даты и времени

  • Второе меню (для перехода в меню нажать кнопку SET, нажимая на кнопку энкодера можно перебирать пункты меню)
    • По канальная регулировка аттенюаторов выходов в диапазоне от 0 до 15 дБ
    • Регулировка яркости подсветки дисплея в обычном режиме и в режиме STANDBY

  • Меню коррекции времени
    • Режим установки-корректировки времени:
      Нажать и удерживать кнопку энкодера, далее нажать кнопку SET, после появится меню корректировки времени, параметры перебираются кнопкой энкодера, ручка энкодера меняет выбранный параметр.

  • Режим MUTE, активируется при помощи кнопки MUTE или ИК пульта

  • Режим STANDBY, активируется при помощи кнопки или ИК пульта

Так как предусмотрена управляемая яркость подсветки дисплея, то можно установить яркость подсветки в основном  режиме и в режиме STANDBY (как правило с пониженной яркостью подсветки), регулировка яркости подсветки осуществляется в меню №2.

Подсветка — убрать перемычку с модуля I2C PCF8574 и подключить вывод модуля к цифровому выходу Arduino D6. Перед подключением замерить ток подсветки который не должен превышать 20 мА (у моего модуля ток не более 15 мА, замер производить между контактами перемычки).

 

Максимальный выходной ток одного выхода Arduino Nano не должен превышать 40 мА.

 

ИК пульт дублирует работу энкодера и кнопок. Для управления регулятором подойдет практически любой пульт ИК, для поддержки Вашего пульта необходимо прописать коды кнопок в скетч:

#define POWER     0x33B800FF
#define VOLUME_UP 0x33B8E01F
#define VOLUME_DW 0x33B810EF
#define MUT       0x33B8946B

Для получения кодов кнопок Вашего пульта загрузите скетч и откройте монитор порта, при нажатии кнопки пульта его код будет отображен в мониторе порта.

#define POWER     0x33B800FF
#define VOLUME_UP 0x33B8E01F
#define VOLUME_DW 0x33B810EF
#define MUT       0x33B8946B
 
 
#include <Wire.h> 
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <Encoder.h>           // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>          // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
#include <boarddefs.h>         // входит в состав библиотеки IRremote
#include <IRremote.h>          // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.zip
#include <PT2258.h> // https://github.com/liman324/PT2258.git
#include <DS3231.h>
 
 PT2258 pt;
 LiquidCrystal_I2C lcd(0x27,20,4);  // Устанавливаем дисплей
 Encoder myEnc(9, 8);// DT, CLK
 IRrecv irrecv(12); // указываем вывод модуля IR приемника
 decode_results ir; 
 DS3231 clock;RTCDateTime DateTime;
 
 
byte v1[8] = {0b00111,0b00111,0b00111,0b00111,0b00111,0b00111,0b00111,0b00111};
byte v2[8] = {0b00111,0b00111,0b00000,0b00000,0b00000,0b00000,0b00000,0b00000};      
byte v3[8] = {0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b11111,0b11111};
byte v4[8] = {0b11111,0b11111,0b00000,0b00000,0b00000,0b00000,0b11111,0b11111};
byte v5[8] = {0b11100,0b11100,0b00000,0b00000,0b00000,0b00000,0b11100,0b11100};
byte v6[8] = {0b11100,0b11100,0b11100,0b11100,0b11100,0b11100,0b11100,0b11100};
byte v7[8] = {0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b00111,0b00111};
byte v8[8] = {0b11111,0b11111,0b00000,0b00000,0b00000,0b00000,0b00000,0b00000}; 
unsigned long times,oldPosition  = -999,newPosition; 
int vol,ch1,ch2,ch3,ch4,ch5,ch6,menu,menu1,menu2,brig,brig0=10,brig1,temp0,i;
bool mute,power,w,w1,gr1,gr2;
byte a[6],d1,d2,d3,d4,d5,d6,e1,e2,e3,x,www,tim_w;
int hour,minut,secon,data,mon,year,time_temp;
byte mesto2[8]={0,10,0,10,0,10,0,10};
byte mesto3[8]={0,0,1,1,2,2,3,3};
int hh,mm,ss,dd,mn,gg;
 
 
void setup(){
  irrecv.enableIRIn();lcd.init();lcd.backlight();Wire.begin();clock.begin();Serial.begin(9600);
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  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);
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении  
  pinMode(10,INPUT);         // МЕНЮ КНОПКА SW энкодера
  pinMode(6,OUTPUT);         // ВЫХОД УПРАВЛЕНИЯ ПОДСВЕТКОЙ
  pinMode(2,INPUT_PULLUP);   // КНОПКА SET
  pinMode(3,INPUT_PULLUP);   // КНОПКА MUTE
  pinMode(4,INPUT_PULLUP);   // КНОПКА POWER
  pinMode(5,OUTPUT);         // Выход управления STANDBY усилителя
  // clock.setDateTime(__DATE__, __TIME__); // Устанавливаем время на часах, основываясь на времени компиляции скетча
  vol = EEPROM.read(0);ch1 = EEPROM.read(1);ch2 = EEPROM.read(2);ch3 = EEPROM.read(3);
  ch4 = EEPROM.read(4);ch5 = EEPROM.read(5);ch6 = EEPROM.read(6);
  brig0 = EEPROM.read(7);brig1 = EEPROM.read(8);
  analogWrite(6, brig0*25);
  delay(500);
  audio();
 
  }
 
void loop(){
/// READ TIME /////////////////////////////////
DateTime = clock.getDateTime();hour = DateTime.hour;minut = DateTime.minute;secon = DateTime.second;
  data = DateTime.day;mon = DateTime.month;year = DateTime.year;
 
/// BUTTON ////////////////////////////////////
if(power==0){
  if(digitalRead(10)==LOW&&menu==1){menu1++;delay(200);times=millis();w=1;w1=1;if(menu1>7){menu1=0;}}
  if(digitalRead(10)==LOW&&menu==2){menu2++;delay(200);times=millis();w=1;w1=1;if(menu2>5){menu2=0;}}
 
  if(digitalRead(2)==LOW&&digitalRead(10)==HIGH){menu++;delay(200);times=millis();cl();w=1;w1=1;menu1=0;if(menu>1){menu=0;}} // SET
  if(digitalRead(2)==LOW&&digitalRead(10)==LOW){menu=2;delay(200);times=millis();cl();w=1;w1=1;lcd.setCursor(2,1);lcd.print("TIME CORRECTION");delay(1000);} // SET time
 
  if((digitalRead(3)==LOW||ir.value==MUT)&&mute==0){mute=1;cl();audio();menu=100;lcd.setCursor(8,1);lcd.print("MUTE");delay(500);}// mute on
  if((digitalRead(3)==LOW||ir.value==MUT)&&mute==1){mute=0;cl();times=millis();w=1;w1=1;menu=0;menu1=0;audio();} // mute off
}
  if((digitalRead(4)==LOW||ir.value==POWER)&&power==0){power=1;cl();times=millis();w=1;w1=1;menu=100;menu1=0;mute=1;audio();brig = brig1;analogWrite(6, brig*25);} // power off
  if((digitalRead(4)==LOW||ir.value==POWER)&&power==1){power=0;cl();times=millis();w=1;w1=1;menu=0;menu1=0;mute=0;audio();brig = brig0;analogWrite(6, brig*25);} // power on
 
  if(power==1){digitalWrite(5,LOW);}else{digitalWrite(5,HIGH);} // output standby
 
/// IR ////////////////////////////////////////
  if ( irrecv.decode( &ir )) {Serial.print("0x");Serial.println( ir.value,HEX);irrecv.resume();times=millis();w=1;w1=1;}// IR приемник - чтение, в мониторе порта отображаются коды кнопок
  if(ir.value==0){gr1=0;gr2=0;}// запрет нажатий не активных кнопок пульта  
 
////////////// VOLUME ///////////////////////////////////////////////////////////////////
 if(menu==0){
     if(ir.value==VOLUME_UP){vol++;gr1=1;gr2=0;cl1();times=millis();w=1;vol_func();audio();}// кнопка > 
     if(ir.value==0xFFFFFFFF and gr1==1){vol++;gr2=0;cl1();times=millis();;w=1;vol_func();audio();}// кнопка >>>>>>
     if(ir.value==VOLUME_DW){vol--;gr1=0;gr2=1;cl1();times=millis();;w=1;vol_func();audio();}// кнопка <
     if(ir.value==0xFFFFFFFF and gr2==1){vol--;gr1=0;cl1();times=millis();w=1;vol_func();audio();}// кнопка <<<<<<
 
   if (newPosition != oldPosition){oldPosition = newPosition;vol=vol+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;vol_func();audio();}
   a[0]= (64-vol)/10;a[1]=(64-vol)%10;
   for(x=0;x<2;x++){switch(x){case 0: e1=11,e2=12,e3=13;break;case 1: e1=14,e2=15,e3=16;break;}digit();}
   lcd.setCursor(0,0);lcd.print("VOLUME");
   lcd.setCursor(0,1);lcd.print("CONTROL");
   lcd.setCursor(0,2);lcd.print("--------------------");
   lcd.setCursor(0,3);
     lcd.print(hour/10);lcd.print(hour%10);lcd.print(":");
     lcd.print(minut/10);lcd.print(minut%10);lcd.print(":");
     lcd.print(secon/10);lcd.print(secon%10);lcd.print(" ");
 
     lcd.print(data/10);lcd.print(data%10);lcd.print("-");
     lcd.print(mon/10);lcd.print(mon%10);lcd.print("-");
     lcd.print(year);
     brig=brig0;
     analogWrite(6, brig*25);
  }  
 
///////// ATT //////////////////////////////////////////////////////////////////////////////
 if(menu==1){
     switch(menu1){
      case 0: temp0 = ch1;break;
      case 1: temp0 = ch2;break;
      case 2: temp0 = ch3;break;
      case 3: temp0 = ch4;break;
      case 4: temp0 = ch5;break;
      case 5: temp0 = ch6;break;
      case 6: temp0 = brig0;break;
      case 7: temp0 = brig1;break;
      }
 
 
   if (newPosition != oldPosition){oldPosition = newPosition;
     temp0=temp0-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;www=1;} 
 
     switch(menu1){
      case 0: ch1 = temp0;if(ch1<0){ch1=0;}if(ch1>15){ch1=15;}break;
      case 1: ch2 = temp0;if(ch2<0){ch2=0;}if(ch2>15){ch2=15;}break;
      case 2: ch3 = temp0;if(ch3<0){ch3=0;}if(ch3>15){ch3=15;}break;
      case 3: ch4 = temp0;if(ch4<0){ch4=0;}if(ch4>15){ch4=15;}break;      
      case 4: ch5 = temp0;if(ch5<0){ch5=0;}if(ch5>15){ch5=15;}break;
      case 5: ch6 = temp0;if(ch6<0){ch6=0;}if(ch6>15){ch6=15;}break;
      case 6: brig0 = temp0;brig0_func();break;
      case 7: brig1 = temp0;brig1_func();break;
      }
 
  au();
  if(menu1<7){brig=brig0;}
  if(menu1==7){brig=brig1;}
  analogWrite(6, brig*25);
  for(i=0;i<8;i++){if(menu1==i){lcd.setCursor(mesto2[i],mesto3[i]);lcd.print(">");}else{lcd.setCursor(mesto2[i],mesto3[i]);lcd.print(" ");}}
 
  lcd.setCursor(1,0);lcd.print("CH1 ");lcd.print(ch1);lcd.print(" ");lcd.setCursor(11,0);lcd.print("CH2 ");lcd.print(ch2);lcd.print(" ");
  lcd.setCursor(1,1);lcd.print("CH3 ");lcd.print(ch3);lcd.print(" ");lcd.setCursor(11,1);lcd.print("CH4 ");lcd.print(ch4);lcd.print(" ");
  lcd.setCursor(1,2);lcd.print("CH5 ");lcd.print(ch5);lcd.print(" ");lcd.setCursor(11,2);lcd.print("CH6 ");lcd.print(ch6);lcd.print(" ");
  lcd.setCursor(1,3);lcd.print("BR_1 ");lcd.print(brig0);lcd.print(" ");lcd.setCursor(11,3);lcd.print("BR_2 ");lcd.print(brig1);lcd.print(" "); 
 } 
 
//////// menu set time /////////////////////////////////////
 if(menu==2){
  hh = DateTime.hour;mm = DateTime.minute;ss = DateTime.second;dd = DateTime.day;mn = DateTime.month;gg = DateTime.year;
  switch(menu2){
      case 0: time_temp = hh;break;
      case 1: time_temp = mm;break;
      case 2: time_temp = ss;break;
      case 3: time_temp = dd;break;
      case 4: time_temp = mn;break;
      case 5: time_temp = gg;break;
      }
 
 
   if (newPosition != oldPosition){oldPosition = newPosition;
     time_temp=time_temp-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;tim_w=1;} 
 
     switch(menu2){
      case 0: hh = time_temp;if(hh<0){hh=0;}if(hh>23){hh=23;}break;
      case 1: mm = time_temp;if(mm<0){mm=0;}if(mm>59){mm=59;}break;
      case 2: ss = time_temp;if(ss<0){ss=0;}if(ss>59){ss=59;}break;
      case 3: dd = time_temp;if(dd<1){dd=1;}if(dd>31){dd=31;}break;      
      case 4: mn = time_temp;if(mn<1){mn=1;}if(mn>12){mn=12;}break;
      case 5: gg = time_temp;if(gg<2022){gg=2022;}if(gg>2100){gg=2100;}break;
      }
 
    lcd.setCursor(0,0);lcd.print("TIME CORRECTION");
    lcd.setCursor(0,1);lcd.print("--------------------");
    lcd.setCursor(0,2);
     if(menu2==0){lcd.print("set hour   ");}
     if(menu2==1){lcd.print("set minute ");}
     if(menu2==2){lcd.print("set seconds");}
     if(menu2==3){lcd.print("set date   ");}
     if(menu2==4){lcd.print("set month  ");}
     if(menu2==5){lcd.print("set year   ");}
 
    lcd.setCursor(0,3);
    lcd.print(hour/10);lcd.print(hour%10);lcd.print(":");
    lcd.print(minut/10);lcd.print(minut%10);lcd.print(":");
    lcd.print(secon/10);lcd.print(secon%10);lcd.print(" ");
 
    lcd.print(data/10);lcd.print(data%10);lcd.print("-");
    lcd.print(mon/10);lcd.print(mon%10);lcd.print("-");
    lcd.print(year);
 
 
    if(tim_w==1){tim_w=0; clock.setDateTime(gg, mn, dd, hh, mm, ss);delay(100);} 
  }
 
/////// EEPROM //////////////////////////////////////
if(millis()-times>10000 && w1==1 && mute==0 && power==0){w1=0;
     EEPROM.update(0,vol);EEPROM.update(1,ch1);EEPROM.update(2,ch2);EEPROM.update(3,ch3);
     EEPROM.update(4,ch4);EEPROM.update(5,ch5);EEPROM.update(6,ch6);
     EEPROM.update(7,brig0);EEPROM.update(8,brig1);
     menu=0;cl();
     }
 
  if(power==1){digitalWrite(7,LOW);
     a[0]=DateTime.hour/10;
     a[1]=DateTime.hour%10;
     a[2]=DateTime.minute/10;
     a[3]=DateTime.minute%10;
     a[4]=DateTime.second/10;
     a[5]=DateTime.second%10;
 
 for(i=0;i<6;i++){
      switch(i){
        case 0: e1=0,e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=7,e2=8,e3=9;break;
        case 3: e1=10,e2=11,e3=12;break;
        case 4: e1=14,e2=15,e3=16;break;
        case 5: e1=17,e2=18,e3=19;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);
  }
  lcd.setCursor(6,0);lcd.print(".");lcd.setCursor(13,0);lcd.print(".");lcd.setCursor(6,1);lcd.print(".");lcd.setCursor(13,1);lcd.print(".");
  lcd.setCursor(0,2);lcd.print("--------------------");
  lcd.setCursor(5,3);lcd.print("POWER  OFF");
  }      
 
 
  }  /// END LOOP
 
 
void au(){if(www==1){audio();www=0;}}
void cl(){ir.value=0;delay(300);lcd.clear();}
void cl1(){ir.value=0;delay(200);} 
void brig1_func(){if(brig1>10){brig1=10;}if(brig1<0){brig1=0;}}
void brig0_func(){if(brig0>10){brig0=10;}if(brig0<0){brig0=0;}}
void audio(){
        pt.clear(); 
      //  pt.setVolume(75); //  int 0...79     
        pt.setVol1(79-(vol+ch1)); //  int 0...79       
        pt.setVol2(79-(vol+ch2)); //  int 0...79 
        pt.setVol3(79-(vol+ch3)); //  int 0...79 
        pt.setVol4(79-(vol+ch4)); //  int 0...79 
        pt.setVol5(79-(vol+ch5)); //  int 0...79 
        pt.setVol6(79-(vol+ch6)); //  int 0...79 
        pt.setMute(mute); // mute 0 - off / 1 - on
  }
 
void to_Timer(){newPosition = myEnc.read()/4;} 
void vol_func(){if(vol<0){vol=0;}if(vol>64){vol=64;}}
 
void digit(){switch(a[x]){
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);}

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=6321#p6321


PT2258 + OLED 0.96 + encoder + IR

 

D10 —  MUTE КНОПКА SW энкодера
D2 —  КНОПКА SET
D4 — КНОПКА POWER
D5 — Выход управления STANDBY усилителя

Скетч — http://forum.rcl-radio.ru/viewtopic.php?id=525


PT2258 + OLED 0.96 + encoder + IR + часы

Время отображается в режиме POWER OFF.

Модуль часов DS3231 или DS1307.

Для коррекции времени перейти в режим STANDBY (POWER OFF) нажать и удерживать кнопку энкодера, для корректировки часов нажать SET, для минут POWER.

http://rcl-radio.ru/wp-content/uploads/2022/07/%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA-%D1%8D%D0%BA%D1%80%D0%B0%D0%BD%D0%B0-%D0%BE%D1%82-2022-07-18-22-20-19.png

D10 —  MUTE КНОПКА SW энкодера
D2 —  КНОПКА SET
D4 — КНОПКА POWER
D5 — Выход управления STANDBY усилителя

Скетч — http://forum.rcl-radio.ru/viewtopic.php?pid=6985#p6985

 

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

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