Музыкальный центр LG cd-962 (частичное восстановление)

led
Offline
Зарегистрирован: 04.11.2012

Здравствуйте.  Давным давно мой друг каким-то мистическим образом умудрился спалить микроконтроллер в музыкальном центре LG CD-962, тогда я ему его частично восстановил управление радио переменным резистором и управление громкостью микросхемой KA2250, за мои труды друг мне подарил с него дисковую часть на запчасти. Но такая конструкция получилась не стабильной в плане удержания частоты принимаемой станции на месте. Тогда, где-то год назад, я ему предложил восстановить микроконтроллерное управление средствами Arduino. После нескольких дней поиска информации и составления программы он получил вполне себе удобный приёмник... И вот недавно этот музыкальный центр опять  попал ко мне на ремонт, и у меня возникла мысль поделиться всем тем, что вышло, а вдруг кто-то тоже как-то сумел спалить процессор и пытается восстановить устройство, не обязательно точно такой же музыкальный центр, на такой  элементной базе строятся куча устройств, а именно синтезатор частоты для приёмника: LC72131 и микросхема управлением звука TDA7439. Родной экранчик пришлось заменить на давно пылившийся у меня знакосинтезирующий 16х2 ЖК с зелёной подсветкой (с русским шрифтом). Все нужные библиотеки я нашел на просторах интернета. Что умеет теперь делать м.центр?:

Включатся и выключаться в дежурный режим. Запоминает своё состояние при выключении и восстанавливает всё при следующем включении даже после отключения от розетки. Имеет память на 32 канала (можно и больше) для радиостанций. Несколько предустановок эквалайзера (их можно сделать сколько угодно или реализовать ручное управление низких средних и высоких частот). Имеет линейный вход за место CD (который был у меня на запчастях:) ) да и аудио диски уже не актуальны. Ну и естественно имеет экран с нужной информации на русском языке...

А вот и скетч:

// Музыкальный центр LG cd-962

#include <inttypes.h>
#include <Wire.h>
//#include <LiquidCrystal.h>
#include <LiquidCrystalRus.h>
#include <SanyoCCB.h>
#include <EEPROM.h>

boolean power = 0;                       // состояние устройства (вкл и выкл)
boolean delayeq = 0;                     // задержка эквалайзера
long previousMillis = 0;                 // храним время последнего нажатия клавиш
long interval = 5000;                    // интервал обновления экрана в бездейсвии
unsigned long currentMillis ;            // переменная для хранения милисекунд...
byte rejim = 3;                          // режим работы
byte vol = 30;                           // громкость
byte eqv = 0; // режим эквалайзера
byte b = 7; byte m = 7; byte t = 7;      // Эквалайзер(и значения по умолчанию*не обязательно)
byte rkanal = 0;                         // канал радио
int memory[33];                          // массив памяти
byte delta;                              // переменная для радио ...
byte key;                                // переменная клавиатуры
byte anim = 0;                           // переменная анимации

byte pll_in1[3];
byte pll_in2[3];
uint16_t FMFrequency = 923;   // MHz * 10 переменная частоты укв
uint16_t AMFrequency = 530;    // KHZ / 10

// Константы клавиатуры  
#define KEY_PRES_P   17
#define KEY_PRES_M   16
#define KEY_MEMORY   15
#define KEY_MODE     14
#define KEY_CLOCK    13
#define KEY_TAPE     12
#define KEY_CD       11
#define KEY_TUNER    10

#define KEY_MEM      9
#define KEY_POWER    8
#define KEY_EQ       7
//#define KEY_REJ       6
#define KEY_BAND      5
#define KEY_VOLP      4
#define KEY_DOWN      3
#define KEY_UP        2
#define KEY_VOLM      1
#define KEY_NONE      0

// LC72131 IN1, byte 0 ------------------------------
#define IN10_R3     7
#define IN10_R2     6
#define IN10_R1     5
#define IN10_R0     4
#define IN10_XS     3
#define IN10_CTE    2
#define IN10_DVS    1
#define IN10_SNS    0

// LC72131 IN2, byte 0
#define IN20_TEST2  7
#define IN20_TEST1  6
#define IN20_TEST0  5
#define IN20_IFS    4
#define IN20_DLC    3
#define IN20_TBC    2
#define IN20_GT1    1
#define IN20_GT0    0

// LC72131 IN2, byte 1
#define IN21_DZ1    7
#define IN21_DZ0    6
#define IN21_UL1    5
#define IN21_UL0    4
#define IN21_DOC2   3
#define IN21_DOC1   2
#define IN21_DOC0   1
#define IN21_DNC    0

// LC72131 IN2, byte 2
#define IN22_BO4    7
#define IN22_BO3    6
#define IN22_BO2    5 //AM mode out1 на микросхеме
#define IN22_BO1    4
#define IN22_IO2    3
#define IN22_IO1    2
#define IN22_IOC2   1
#define IN22_IOC1   0

// LC72131 DO0, byte 0
#define DO0_IN2     7
#define DO0_IN1     6
#define DO0_UL      4

// For function YST93xSetMode
#define YST93x_MONO    1
#define YST93x_STEREO  2
#define YST93x_MUTE    3
#define YST93x_UNMUTE  4
#define YST93x_BAND_FM 5
#define YST93x_BAND_AM 6

// Acceptable IF frequency deviation window (for the PLL) when searching for radio stations
// You may need to tweek these values to have a reliable "scan" mode
#define FM_TUNED_WINDOW 180
#define AM_TUNED_WINDOW 20

byte band = YST93x_BAND_FM;
byte tuned = 0;

SanyoCCB ccb(A3, A2, 1, 0);              // Выводы: DO CL DI CE (настройка подключения синтезатора частоты)
//LiquidCrystal lcd(8, 9, 10, 11, 12, 13); // настройка подключения экрана
LiquidCrystalRus lcd(8, 9, 10, 11, 12, 13);

// ************************************ SETUP **********************************************************
void setup()
{ 
  lcd.begin(16, 2);             // настройка экрана
  Wire.begin();                 // активация i2c интерфейса
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);            // sw power
  pinMode(7, OUTPUT);           // tape
  pinMode(6, OUTPUT);           // radio
  pinMode(5, OUTPUT);           // Cd
  pinMode(4, OUTPUT);           // mute
  
  digitalWrite(2, power);
  digitalWrite(4, !power);
  initTDA7439();                // инициализация микросхемы звука (уже бестолковая)
  
  for (byte i=0; i<=64; i++)    // Цикл записи в массив memory[] 32х значений из EEPROM
   { 
    memory[i/2] = EEPROMReadInt(i);
    i++;                        // принудительное добавление единицы,т.к. значения 2х байтовые...
   }
                                // восстановление состояния устройства с последнего выключения питания
   rejim =  EEPROM.read(64);    // Режим                 
   vol  =   EEPROM.read(65);    // Громкость
   rkanal = EEPROM.read(66);    // канал приёмника
   eqv =    EEPROM.read(67);    // эквалайзер

                                // Инициализация синтезатора частоты радио -------
  ccb.init();
  delay(1000);
  YST93xInit();
  YST93xSetMode(YST93x_BAND_FM);
  YST93xSetMode(YST93x_STEREO);
  tuned = YST93xTune(FMFrequency);
  
}


// ************************************ LOOP **********************************************************
void loop()
{ 
     // lcd.setCursor(16, 1); 
     // lcd.print("    "); 
     // lcd.setCursor(16, 1);
     // lcd.print(analogRead(A0));
    //  lcd.setCursor(16, 2); 
    //  lcd.print("    "); 
    //  lcd.setCursor(16, 2);
    //  lcd.print(analogRead(A1));
    // delay(100); // Всё выше закомментированно для теста аналоговых кнопок для экрана 20х4
 
   delta = 0; // переменная для радио ...

  // Обработка нажатых кнопок 
  while (power == 0) {  if (getKey() == KEY_POWER) {delayKey(1); OnOff();}  } // крутимся на месте пока не включимся
  key = getKey();
  if(key != KEY_NONE) {  
    switch(key) {
      case KEY_MEMORY: if(rejim == 2) { if (delayKey(0)) {WriteKanal(); lcd.setCursor(13, 1); lcd.print("Зап"); while(getKey() != KEY_NONE); delay(400); lcd.setCursor(14, 1); lcd.print("Кн"); } else { rkanal++; if (rkanal >= 32) {rkanal=0;} radio(1); displey(); } }break; 
      case KEY_PRES_P: if(rejim == 2) {delayKey(1); delay(100); rkanal++; if (rkanal >= 32) {rkanal=0;} radio(1); displey();}  break; 
      case KEY_PRES_M: if(rejim == 2) {delayKey(1); delay(100); rkanal--; if (rkanal > 200) {rkanal=31;} radio(1); displey();}  break;
      case KEY_POWER:  delayKey(1); OnOff(); break; // knopka power
      case KEY_MODE:   delayKey(0); rejim++; if (rejim > 3) {rejim=0;} RejimRaboti(rejim); break; // Режим
      case KEY_TAPE:   delayKey(1); rejim=0; RejimRaboti(rejim); break;
      case KEY_CD:     if (delayKey(0)) rejim=1; else rejim=3; RejimRaboti(rejim); while(getKey() != KEY_NONE); delay(400);break;
      case KEY_TUNER:  delayKey(1); rejim=2; RejimRaboti(rejim); radio(0); break;
      case KEY_VOLM:   delayKey(1);vol++; delayeq = 0; if  (vol > 47) {vol=56;} volume(vol); break; // Громкость -
      case KEY_VOLP:   delayKey(1);vol--; delayeq = 0; if  (vol < 1 || vol > 200) {vol=0;} if  (vol > 47) {vol=47;} volume(vol); break;  // Громкость +
      case KEY_EQ:     delayKey(0);eqv++; delayeq = 1; if (eqv > 7) {eqv=0;} eq(); break;
      case KEY_UP:    if(rejim == 2) {delayKey(1); if (rejim == 2) {delta = +1; radio(0);}} break;
      case KEY_DOWN:  if(rejim == 2) {delayKey(1); if (rejim == 2) {delta = -1; radio(0);}} break;
      case KEY_BAND:  if(rejim == 2) {delayKey(0);
                      switch(band) {
                       case YST93x_BAND_FM:
                       YST93xSetMode(YST93x_BAND_AM);
                       tuned = YST93xTune(AMFrequency);
                       displey();
                       break;
                       case YST93x_BAND_AM:
                       YST93xSetMode(YST93x_BAND_FM);
                       tuned = YST93xTune(FMFrequency);
                       displey();
                       break;      }   
        } // switch band
    } // switch key

  } // if(key)
  
  currentMillis = millis(); 
  if(currentMillis - previousMillis > interval ) // Условие на обновление экрана раз в interval (пока задействованно только под эквалайзер и громкость)
  {
    previousMillis = currentMillis;  
    anim++;
    if (anim > 2) anim = 0;
    //delayeq = 0;
    displey();
  }
  
}


byte getKey() { // Функция опроса клавиатуры
  int keypad0;
  int keypad1;
  byte key = KEY_NONE;
  
  keypad0 = analogRead(A0);
  keypad1 = analogRead(A1);
  // Аналоговые кнопки 0
  if(keypad0 < 750) key = KEY_VOLP;  
  if(keypad0 < 630) key = KEY_VOLM;  
  if(keypad0 < 550) key = KEY_EQ;  
  if(keypad0 < 450)  key = KEY_PRES_P;
  if(keypad0 < 340) key = KEY_PRES_M;  
  if(keypad0 < 230) key = KEY_UP;  
  if(keypad0 < 160) key = KEY_DOWN;  
  //if(keypad0 < 95) key = KEY_;  
  //if(keypad0 < 10)  key = KEY_;
  // Аналоговые кнопки 1
  if(keypad1 < 530)  key = KEY_MEMORY;
  if(keypad1 < 440)  key = KEY_MODE;  
  if(keypad1 < 250)  key = KEY_CLOCK;  
  if(keypad1 < 160)  key = KEY_TAPE;  
  if(keypad1 < 95)   key = KEY_CD;  
  if(keypad1 < 10)   key = KEY_TUNER;
  // Кнопка POWER --------------------------
  if(digitalRead(3) == 0 ) key = KEY_POWER;
  return key;
}
// --------------------------------------------------------------------------------------------------
byte delayKey(byte no) // Вункция анализа длительного нажатия кнопки и компенсации дребезга кнопок...
{                      // Вызывается delayKey(1); : 1- не анализировать дл. нажатие, 0- анализировать...
byte x = 0;            // функция возвражает 1 если определила длительное нажатие клавиши и 0 - короткое.
byte y = 0;
delay(70);
key = getKey();
if (no == 0)
{
while(key != KEY_NONE && y < 150 ) 
{
 key = getKey();
 delay(10);
 y++;
}
if (y >= 149) x=1;
}
  // lcd.setCursor(19, 0); 
  // lcd.print(x);
return x;
}
// --------------------------------------------------------------------------------------------------
// Инициализация  YST93xInit
void YST93xInit() {
  memset(pll_in1, 0, 3);
  memset(pll_in2, 0, 3);
  bitSet(pll_in2[0], IN20_IFS);   // IF counter in normal mode
  bitSet(pll_in2[1], IN21_UL0);   // Phase error detection width = 0us
  bitSet(pll_in2[2], IN22_BO2);   // Mute off / normal tuner mode
  bitSet(pll_in1[0], IN10_XS);    // Кварц 7.2МГц
}

// --------------------------------------------------------------------------------------------------
// Установки YST93xSetMode  

void YST93xSetMode(uint8_t mode) {
  switch(mode) {
    case YST93x_STEREO:
      bitClear(pll_in2[2], IN22_BO3);
      break;

    case YST93x_MONO:
      bitSet(pll_in2[2], IN22_BO3);
      break;

    case YST93x_MUTE:
     // bitClear(pll_in2[2], IN22_BO2);
      break;

    case YST93x_UNMUTE:
      //bitSet(pll_in2[2], IN22_BO2);
      break;

    case YST93x_BAND_FM:
      band = YST93x_BAND_FM;
      bitWrite(pll_in1[0], IN10_R0,  1); // Reference frequency = 50kHz
      bitWrite(pll_in1[0], IN10_R3,  0); //
      bitWrite(pll_in1[0], IN10_DVS, 1); // Programmable Divider divisor = 2
      bitWrite(pll_in2[0], IN20_GT0, 0); // IF counter mesurement period = 32ms
      bitWrite(pll_in2[0], IN20_GT1, 1); //
      bitWrite(pll_in2[1], IN21_DZ0, 1); // Dead zone = DZB
      bitWrite(pll_in2[1], IN21_DZ1, 0); //
      bitWrite(pll_in2[2], IN22_BO1, 0); // FM mode
      bitWrite(pll_in2[2], IN22_BO2, 1); // AM mode out1 на микросхеме
      break;
    
    case YST93x_BAND_AM:
      band = YST93x_BAND_AM;
      bitWrite(pll_in1[0], IN10_R0,  0); // Reference frequency = 10kHz
      bitWrite(pll_in1[0], IN10_R3,  1); //
      bitWrite(pll_in1[0], IN10_DVS, 0); // Programmable Divider divisor = 1
      bitWrite(pll_in2[0], IN20_GT0, 1); // IF counter mesurement period = 8ms
      bitWrite(pll_in2[0], IN20_GT1, 0); //
      bitWrite(pll_in2[1], IN21_DZ0, 0); // Dead zone = DZC
      bitWrite(pll_in2[1], IN21_DZ1, 1); //
      bitWrite(pll_in2[2], IN22_BO1, 1); // AM mode
      bitWrite(pll_in2[2], IN22_BO2, 0); // AM mode out1 на микросхеме
      break;
  }
  ccb.write(0x82, pll_in1, 3); 
  ccb.write(0x92, pll_in2, 3); 
}


// --------------------------------------------------------------------------------------------------
//Функция установки частоты тюнера. Возвращает 1, если она настроена
//или в противном случае 0. 

// The frequency divisors was chosen in a way the frequency *
// representation can be directly sent to the PLL and is    *
// easy to represent:                                       *
// - FM mode (divisor = 100): frequency (MHz) * 10          *
// - AM mode (divisor = 10):  frequency (kHZ) / 10          *
//*************************************************************
byte YST93xTune(uint16_t frequency) {
  uint16_t fpd = 0;
  byte i = 0;
  byte r[3];
  unsigned long IFCounter = 0;
  
  switch(band) {
    case YST93x_BAND_FM:
      // FM: fpd = (frequency + FI) / (50 * 2)
      fpd = (frequency + 107);
      break;
      
    case YST93x_BAND_AM:
      // AM: fpd = ((frequency + FI) / 10) << 4
      fpd = (frequency + 45) << 4;
      break;
      
    default: return 1;
  }

  YST93xSetMode(YST93x_MUTE);   // YST93x only injects FI signal into the PLL when in MUTE mode

  // Reset the IF counter and program the Frequency Programmable Divider (fpd)
  bitClear(pll_in1[0], IN10_CTE);
  pll_in1[1] = byte(fpd >> 8);
  pll_in1[2] = byte(fpd & 0x00ff);
  ccb.write(0x82, pll_in1, 3);

  // Start the IF counter
  bitSet(pll_in1[0], IN10_CTE);
  ccb.write(0x82, pll_in1, 3);

  // Wait for PLL to be locked (DO0_UL == 1)
  while(i < 20) {
    delay(50);
    ccb.read(0xa2, r, 3);  // Discard the 1st result: it is latched from the last count (as said on the datasheet)
    ccb.read(0xa2, r, 3);  // The 20 rightmost bits from r[0..2] are the IF counter result
    i = (bitRead(r[0], DO0_UL)) ? 100 : i + 1;
  }
  
  YST93xSetMode(YST93x_UNMUTE);   // Mute off / normal tuner mode

  if(i == 100) {
    // PLL is locked.  If the IF deviation is within the defined (window) interval,
    // the radio is likely to be tuned.
    // Note: this "tuned" detection method is not recommended on the LC72131 datasheet as 
    // it can give false positive results.  A better approach would be to get the "tuned"
    // flag from a RDS decoder with signal quality detection (e.g.: PT2579 or Philips SAA6588)
    // connected to the YST93x tuner module "RDS Output" pin. SAA6588 is more powerful/popular, 
    // but PT2579 looks a lot easier to use as it is not programmable and has a dedicated
    // signal quality output pin.
    IFCounter = (r[0] & 0x0f);
    IFCounter = (IFCounter << 16) | (unsigned long)(r[1] << 8) | (r[2]);
   // Serial.println(IFCounter);
    switch(band) {
      case YST93x_BAND_FM:
        // Expected value: IF (10.7MHz) * Mesurement period (32ms, as set via GT[1..0]) = 342400
        if((IFCounter > 342400) && ((IFCounter - 342400) < FM_TUNED_WINDOW)) return 1;
        if((IFCounter < 342400) && ((342400 - IFCounter) < FM_TUNED_WINDOW)) return 1;
        break;
      case YST93x_BAND_AM:
        // Expected value: IF (450kHz) * Mesurement period (8ms, as set via GT[1..0]) = 3600
        // Note: scan mode in AM is really poor.  I have done my best in tweaking it, but it barely works
        if((IFCounter > 3600) && ((IFCounter - 3600) < AM_TUNED_WINDOW)) return 1;
        if((IFCounter < 3600) && ((3600 - IFCounter) < AM_TUNED_WINDOW)) return 1;
        break;
    }
  }
  return 0; 
}

// --------------------------------------------------------------------------------------------------
//опрос приёмника на состояние stereo (1 - стерео))
byte YST93xIsStereo() {
  byte r[3];
  
  ccb.read(0xa2, r, 3);
  return(bitRead(r[0], DO0_IN2) ? 0 : 1);
}


// --------------------------------------------------------------------------------------------------
void WriteKanal() // функция  для записи станции в память
{ 
EEPROMWriteInt(rkanal*2, FMFrequency);
memory[rkanal] = EEPROMReadInt(rkanal*2);
}

// --------------------------------------------------------------------------------------------------

void radio(byte m) // функция радио
{
  switch(band) {
    case YST93x_BAND_FM:
    //  lcd.print("FM ");
    //  lcd.setCursor((FMFrequency < 1000) ? 4 : 3, 3); lcd.print((float)FMFrequency / 10, 1);
    //  lcd.print("MHz ");
    displey();
      break;
    case YST93x_BAND_AM:
   //   lcd.print("AM ");
   //   lcd.setCursor((AMFrequency < 100) ? 4 : 3, 2); lcd.print(AMFrequency * 10);
    //  lcd.print("KHz ");
    displey();
      break;
  }

    // Change the station  
    switch(band) {
      case YST93x_BAND_FM:
        do{
          FMFrequency += delta;
          if(FMFrequency > 1085) FMFrequency = 630; //возврят к началу
          if(FMFrequency < 630)  FMFrequency = 1085; //возврат к концу
          if(m == 1) FMFrequency = memory[rkanal]; // частота из памяти
          tuned = YST93xTune(FMFrequency);
          
          displey();
        } while(tuned);
        break;
        
      case YST93x_BAND_AM:
        do{
          AMFrequency += delta;
          if(AMFrequency > 116) AMFrequency = 53;
          if(AMFrequency < 53)  AMFrequency = 116;
          tuned = YST93xTune(AMFrequency);

       //   lcd.setCursor(3, 3);
     //     if(AMFrequency < 100) lcd.print(' ');
     //     lcd.print(AMFrequency * 10);
        } while(tuned);
        break;       
    } // switch 
    
   // YST93xSetMode(YST93x_STEREO);
}

// --------------------------------------------------------------------------------------------------
void OnOff()
{ 
  while(digitalRead(3)==0) 
  delay(80);
  volume(56);
  power = !power;
  digitalWrite(4, !power); 
    if (power == 1)
     {// power 
     // volume(56); 
     digitalWrite(2, power);
     delay(100);// Задержка обязательна, иначе радио стартует не всегда с первого раза.
      radio(1);
      //balans----------------  
      Wire.beginTransmission(0b1000100);
      Wire.write(0b0000111); 
      Wire.write(0b0000000); 
      Wire.endTransmission();
      //delay(1);
      Wire.beginTransmission(0b1000100);
      Wire.write(0b0000001); 
      Wire.write(0b0000000); 
      Wire.endTransmission();
      //delay(1);
      //------------------ gein
      Wire.beginTransmission(0b1000100);
      Wire.write(0b0000110); 
      Wire.write(0b0000000); // Усиление на ноль
      Wire.endTransmission();
      //delay(1);
      //eq(b,m,t); 
      eq();
      RejimRaboti(rejim);
      delay(400);
      byte volstart  =  EEPROM.read(65);
      for (byte i = 47; i>=volstart; i--) {vol=i; volume(vol); delay(15);} // Плавное восстановление громкости... 
     } // if power
    else
     { // сохраняем состояния устройства перед выключением
      if (vol > 30) EEPROM.write(65,vol); else EEPROM.write(65,30); // сохраняем громкость но не больше -30Дб, чтобы не обосраться при следующем включении
      EEPROM.write(64,rejim);                      
      EEPROM.write(66,rkanal);
      EEPROM.write(67,eqv);
       lcd.clear();  // балавство...VVV
       lcd.print(" Взломано ");
       delay(1000);
       lcd.setCursor(0, 0);
       lcd.print(" Димкой  ");
       delay(1500);
      displey();

      digitalWrite(2, power);
     }// else power
 // displey();
}

// ------------------------ Режим работы --------------
void RejimRaboti(byte rejim)
{ // режимы работы 
  Wire.beginTransmission(0b1000100);
  Wire.write(0b0000000); 
  Wire.write(rejim); 
  Wire.endTransmission();
  delay(100); 
  
  displey();
}
// -----------------------Громкость ----------------------
void volume(byte vol)
{ // Громкость
  Wire.beginTransmission(0b1000100);
  Wire.write(0b00000010); 
  Wire.write(vol); 
  Wire.endTransmission();
  delay(100); 
  
  displey();
} 
// --------------------------- Эквалайзер --------------
//void eq(byte b, byte m, byte t)
void eq()
{
  // от -14Дб - 0Дб: значения 0 - 7 //  от 0Дб - +14Дб: значения 15 - 8
 if (eqv == 0) { b=7; m=7; t=7; }  // flat
 if (eqv == 1) { b=9; m=7; t=12; } // Rock
 if (eqv == 2) { b=9; m=2; t=10; } // Rock 2
 if (eqv == 3) { b=7; m=7; t=11; } // Classic
 if (eqv == 4) { b=2; m=7; t=2; }  // pop
 if (eqv == 5) { b=11; m=7; t=7; }  // Bass 1
 if (eqv == 6) { b=9; m=7; t=7; }  // Bass 2
 if (eqv == 7) { b=8; m=7; t=7; }  // Bass 3
  
  //низкие
  Wire.beginTransmission(0b1000100);
  Wire.write(0b00000011); 
  Wire.write(b); 
  Wire.endTransmission();
  //delay(1);
  
  //Средние
  Wire.beginTransmission(0b1000100);
  Wire.write(0b00000101); 
  Wire.write(m); 
  Wire.endTransmission();
 // delay(1);
    
  //высокие
  Wire.beginTransmission(0b1000100);
  Wire.write(0b00000101); 
  Wire.write(t); 
  Wire.endTransmission();
  delay(300); 
  
  displey();
}
// --------------------- Инициализация ----------------------------
void initTDA7439()
{ 
  //digitalWrite(2, power);
  displey();
}
// --------------------------- Экран -------------------------------------
void displey()
{
  if (power == 0)
   {             // Что показываев на экране в выключенном состоянии
    lcd.clear();
    lcd.setCursor(1, 1);
    lcd.print("РЕЖИМ ОЖИДАНИЯ"); 
    digitalWrite(5,0);digitalWrite(6,0);digitalWrite(7,0); // тушем светодиоды режимов
   }
  else
  {
  
  
  lcd.setCursor(0, 0);
  lcd.print("       "); // Стирания области режимов
  lcd.setCursor(0, 0);
  if(rejim == 0)       // Режим Касеты
                 {lcd.print("КАССЕТА");digitalWrite(7,1);digitalWrite(6,0);digitalWrite(5,0);
                  lcd.setCursor(0, 1);
                  lcd.print(" [               ");
                  lcd.setCursor(2+anim, 1);
                  lcd.print(">  ");}
  if(rejim == 3)      // Режим CD но реально задействованно под линейный вход
                 {lcd.print(" AUX");digitalWrite(5,1);digitalWrite(6,0);digitalWrite(7,0);
                  lcd.setCursor(0, 1);
                  lcd.print("Линейный вход   ");
                  lcd.setCursor(13+anim, 1);
                  lcd.print(".  ");}
  if(rejim == 2)      // Режим Радио
                 {lcd.print("РАДИО");digitalWrite(6,1);digitalWrite(7,0);digitalWrite(5,0);
                  lcd.setCursor(0, 1);
                  lcd.print("FM ");
                  lcd.setCursor((FMFrequency < 1000) ? 4 : 3, 1); lcd.print((float)FMFrequency / 10, 1);
                  lcd.print("МГц ");
                  lcd.setCursor(3, 1);
                  if(FMFrequency < 1000) lcd.print(' ');
                  lcd.print((float)FMFrequency / 10, 1);
                  lcd.setCursor(12, 1);
                  if (rkanal > 8) {lcd.print(rkanal+1);} else {lcd.print(" "); lcd.print(rkanal+1);}
                  lcd.setCursor(14, 1);
                  lcd.print("Кн"); }
  if(rejim == 1)     // режим Линейного входа но реально задействован под диск которого нет
                 {lcd.print(" ДИСК");digitalWrite(5,0);digitalWrite(6,0);digitalWrite(7,0);
                  lcd.setCursor(0, 1);
                  lcd.print("  ()            ");}
                  
                  
  if (delayeq == 0) // Условие отображения громкости или эквалайзера на экране
   {
   lcd.setCursor(7, 0); //Громкость
   lcd.print(" Гр:-  Дб");
   lcd.setCursor(12, 0);
   if(vol == 56) lcd.print("----"); else lcd.print(vol);
   }
   else
   {
   lcd.setCursor(5, 0);  // Эквалайзер
   lcd.print(" Эк:       ");
   lcd.setCursor(9, 0);
   if(eqv == 0) lcd.print("Линейн.");
   if(eqv == 1) lcd.print(" Рок");
   if(eqv == 2) lcd.print(" Рок 2");
   if(eqv == 3) lcd.print("Классик");
   if(eqv == 4) lcd.print(" Поп");
   if(eqv == 5) lcd.print(" Бас 1");
   if(eqv == 6) lcd.print(" Бас 2");
   if(eqv == 7) lcd.print(" Бас 3");
   delayeq = 0;
   previousMillis = currentMillis-2000; // коррекция интервала времени для отображения режимов эквалайзера после нажатия кнопки EQ
   }                  

  } // else power
}  

///  ------------------ int в EEPROM ------------------------------------
//Функция записи 2х байтов в EEPROM по адресу и адресу + 1
void EEPROMWriteInt(int p_address, int p_value)
        {
        byte lowByte = ((p_value >> 0) & 0xFF);
        byte highByte = ((p_value >> 8) & 0xFF);

        EEPROM.write(p_address, lowByte);
        EEPROM.write(p_address + 1, highByte);
        }

//Функция чтения 2х байтов из EEPROM по адресу и адресу + 1
unsigned int EEPROMReadInt(int p_address)
        {
        byte lowByte = EEPROM.read(p_address);
        byte highByte = EEPROM.read(p_address + 1);

        return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
        }

К сожалению конечную версию кода я у себя не нашёл, но выше представленный отличается только небольшой оптимизацией в виде замены некоторых IF на  switch и т.п.

Ссылка на всё (Скетч, библиотеки, схема м.центра...): http://yadi.sk/d/h7YdOQztDnxvG

Вот несколько фото:

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

прикольно

toc
Offline
Зарегистрирован: 09.02.2013

Супер! Не хватает фотографии пациента "в полный рост". :) Далее моё скромное мнение. 

1. При включении делаете плавное восстановление громкости. Во время него кнопка уменьшения громкости работает?

2. "крутимся на месте пока не включимся" тут сто́ит включать спящий режим МК

3. слишком много глобальных переменных

4. название метода (процедуры или функции) должно содержать глагол. Хорошее: getKey ; плохие: OnOf, РежимРаботы, Радио... 

5. Fm чип понимает Rds?

p.s. недавно из моей машины какая-то шпана украла панельку от магнитолы 15-тилетней давности. Магнитолу оставили. Видно не подошла, без cd и без мп3. Вот бы в неё дуину вставить.

led
Offline
Зарегистрирован: 04.11.2012

1. Нет в этот момент ничего не может произойти кроме как прибавляться звук. в принципе не особо и нужно прибавление идёт только максимум до -30 дб или до той громкости  при которой было выключино и опять же не громче -30 дб (это не особо громко), хотя как вариант не помешало бы и реализовать обработку кнопку уменьшения громкости.

2. Честно, я даже и не знаю как средствами ардуино перевести контролёр в спящий режим.

3. даже и не знаю что ответить :)

4. Ну как то мне наглядней так писать...

5. Нет не поддерживает... да и хозяин устройства отказался даже от реализации автоматического сканирования р.станций и от АМ диапазона, мне самое главное нужно было задействовать ручное переключение частоты и возможность занесения их в память.

И сейчас у него есть желание туда встроить MP3 плеер...

led
Offline
Зарегистрирован: 04.11.2012

Да и чуть не забыл, вспомнил я здесь ошибку в коде: тип переменной delta должен быть int8_t, а не byte, иначе переключение частоты в минусовую сторону будет не корректным...

А вот фото пациента в полный рост:

p.s. ..почему то я не могу отредактировать своё первое сообщение...

Valery1111
Offline
Зарегистрирован: 17.01.2014

Не компилируется, выдает ошибку:
C:\Users\1\Desktop\Новая папка\arduino-1.0.5-r2\hardware\arduino\cores\arduino/main.cpp:14: undefined reference to `loop'
вопрос к автору, в чем может быть проблема ?

 

maksim
Offline
Зарегистрирован: 12.02.2012

Valery1111 пишет:

в чем может быть проблема ?

В том что вы не смогли скопипастить код. Компилятор не видит в вашем коде функцию:

void loop()

 

a5021
Offline
Зарегистрирован: 07.07.2013

toc пишет:

3. слишком много глобальных переменных

Много? Вы "много" не видели еще. В США не так давно была скандальная история с самопроизвольным включением акселератора (педали газа) в одной из моделей Тойот. Расследование там было долгое и путанное, но помимо прочего, обнаружился примечательный факт, что в программном обеспечении главного автомобильного мозга (какой-то специализированный автомобильный МК фирмы NEC) оказалось больше одиннадцати тысяч глобальных переменных.

Цитата:

4. название метода (процедуры или функции) должно содержать глагол. Хорошее: getKey ; плохие: OnOf, РежимРаботы, Радио... 

В ардуине, выходит, одни плохие: setup(), loop()... :)

Valery1111
Offline
Зарегистрирован: 17.01.2014

maxim пишет:В том что вы не смогли скопипастить код. Компилятор не видит в вашем коде функцию:

155 void loop()

в скетче эта функция присутствует, изменение переменной int8_t delta; произвел
вот
void loop()
{
// lcd.setCursor(16, 1);
// lcd.print(" ");
// lcd.setCursor(16, 1);
// lcd.print(analogRead(A0));
// lcd.setCursor(16, 2);
// lcd.print(" ");
// lcd.setCursor(16, 2);
// lcd.print(analogRead(A1));
функция присутствует, не могли бы ВЫ скомпи
лировать скетч из архива и прояснить ситуацию?
Ваша статья единственная такого рода, тем и ценна
мне бы хотелось расширить диапазон частот , а именно 118-136 мгц.т.е Авиа
дальнейшая обработка после ПЧ 10,7- вторая узкополосная 455кгц АМ
не сочтите за наглость, но хотел бы готовый скетч, сам в програмировании.....

Valery1111
Offline
Зарегистрирован: 17.01.2014

да еще проблема в не русифицированном ЖКИ, наверное  муть будет отображать ?

да и шаг перстрйики нужен 25кгц, вообщем тема уже другая, хотелось бы расчитывать на помощь

 

led
Offline
Зарегистрирован: 04.11.2012

Вот сам же свой архив скачал - компилируется (и тот что в первом посте код тоже)

Да и в этом коде не задействован АМ диапазон (нуждается в неболшем "допиле" кода, хозяин устройства не нуждался в этом диапазоне, я и по нему не заморачивался)

Да и вообще если вам нужно только радио смотрите пример в библиотеке SanyoCCB только там реализация на 4.5мгц кварц.

Если в ЖКИ нет русских символов, то расскоментируйте строки:

5 и 113 и закомментируйте 6 и 114 и используйте англ. символы.

тип переменной delta влияет толко на вычитание на шаг от рабочей частоты т.е. за нажатие кнопки: |<<

led
Offline
Зарегистрирован: 04.11.2012

И ещё.

Данный музыкальный центр не осилил  перестроится на частоту выше 116.5МГц, что бы поднять выше нужно переделывать схему...

Valery1111
Offline
Зарегистрирован: 17.01.2014

понятно. наверное с перекрытием по диапазону у варикапов мало напряжения, да и контуром гетеродина поиграться можно
у меня есть несколько блочков о LG на LC72131 с ними поиграться хочу, в плане перестройки входных и гет контуров,

наверное и управляющее напряжение на варикапы поднять прийдется, дело только в управлении

сейчас по новой скачаю архив и попробую
спасибо за оперативный ответ, буду пробовать

Valery1111
Offline
Зарегистрирован: 17.01.2014

странно. но у меня все по прежнему

вот

c:/users/1/desktop/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5/crtm328p.o:(.init9+0x0): undefined reference to `main'
может в моем клоне 328  памяти мало ?
 или библиотеки править нужно ?

a5021
Offline
Зарегистрирован: 07.07.2013

при чем тут железка? это линкер ругается. не может собрать программу перед загрузкой.

Valery1111
Offline
Зарегистрирован: 17.01.2014

а5021
Ваш ответ очень информативен.......
так кто то может КОНКРЕТНО подсказать , как решить эту проблему ?
Выше писал, что с программированием не дружу 

a5021
Offline
Зарегистрирован: 07.07.2013

Я тут собрался доказать по-быстрому все недоказанные к сему моменту теоремы, так вы не могли бы мне помочь? С математикой и физикой я не дружу, но это не должно быть помехой.

Вам никто "КОНКРЕТНО" не подскажет, т.к. вы сами не можете "КОНКРЕТНО" описать собственную проблему. У вас не компилируется исходник. Больше всего это похоже на то, что вы его не смогли правильно скопировать. При чем тут количество памяти в ардуине? Отключите его вообще, это ни на что не повлияет.

 

Valery1111
Offline
Зарегистрирован: 17.01.2014

как еще конкретней ?

я привожу сообщение компилятора см.выше
исходник беру из архива, проверял и с того , что в посте, результат один , только сообщения об ошибке разные.
на нормальных тех. форумах, если решили помочь новичку - скажут сделай  то либо другое , отпиши, не поможет, будем дальше думать...

причем люди уважаемые и без всякой бровады и с заявкой на тенденциозность
благодарю за помощь
хотел как быстрей , а вышло как всегда .....

a5021
Offline
Зарегистрирован: 07.07.2013

Valery1111 пишет:

исходник беру из архива, проверял и с того , что в посте, результат один , только сообщения об ошибке разные.

Ой, мама! Как это результат один, если ошибки разные? Это разные результаты. И причины приведшие к таким результатам могут быть разными и их может быть много.  Но главная причина кроется, похоже, в вас. Вы не хотите даже сопоставить эти два факта.

Цитата:

на нормальных тех. форумах, если решили помочь новичку - скажут сделай  то либо другое , отпиши, не поможет, будем дальше думать... причем люди уважаемые и без всякой бровады и с заявкой на тенденциозность

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

И бываю я на ваших радиолюбительских форумах, где "люди уважаемые и без всякой бровады" в сотый раз пересказывают всем встречным и поперечным какую-нибудь жуткую банальность, которую запомнили с тех пор, когда сорок лет назад посещали радиокружок во дворце пионеров. Ничего не имею против. Кому-то и такая компания кажется приятной.

Valery1111
Offline
Зарегистрирован: 17.01.2014

утихни боец
не можешь не вякай

a5021
Offline
Зарегистрирован: 07.07.2013

Я смотрю вы решили переместиться на поле, где чувствуете себя очень уверенно. Может еще по матери чего задвините, раз уж с компилятором не срослось?

 

led
Offline
Зарегистрирован: 04.11.2012

Чего вы тут закаккали тему  то всю...

Valery1111, максимум что я могу помочь это выслать вам архив вместе с Arduino IDE и всеми нужными библиотеками, где весь этот код компилируется 100%.

Valery1111
Offline
Зарегистрирован: 17.01.2014

Согласен, плохо как то получилось

у меня версия IDE 1.0.5
beta версию не установливал
из архива скачал скектч и библиотеки по Вашей ссылке
библиотеки скопировал в папку libraries, перезапустил IDE
при компиляции выдает ошибку
c:/users/1/desktop/arduino/arduino-1.0.5-r2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5/crtm328p.o:(.init9+0x0): undefined reference to `main'
что делаю не так. прошу ткуть носом

P.S
пример по VTS93xx из библиотеки SanyoCCBmaster  компилируется нормально
maxim  ( судя по форуму адекватный человек) указывал в посте 6 на отсутствие оператора loop  ,все есть

led
Offline
Зарегистрирован: 04.11.2012

Valery1111, понял в чём проблема..., переименуйте папку со скетчем на lg и сам скетч внутри на lg.ino,

либо скачайте этот архив:

http://yadi.sk/d/XVvzi0qwGYbSM

Valery1111
Offline
Зарегистрирован: 17.01.2014

Все .спасибо, все скомпилировалось сразу и без проблем
сегодня для пробы запустил китайскую балалайку (VST93xx)  из примера
но по поводу Вашего сетча у меня возможно возникнут вопросы - если Вы не против,

я конечно попробую разобраться в коментариях сам ,но...
да и мне не все функции нужны будут
И еще вопрос , я пытался разобраться где задается шаг перестройки 50 или 25кгц
мне нужен 25 кгц кварц 7.2
Укажите пожалуйста строки , где эти настройки устанавливаются, если я вам еще не надоел..
еще раз спасибо, за то что первую проблему помогли разрулить

led
Offline
Зарегистрирован: 04.11.2012

Valery1111, открываете datasheet на LC72131 , находите там таблицу 2. DI Control Data Functions, там смотрите пункты:

Reference divider data R0 to R3 и XS - там расписано какие биты за что отвечают.

Применяете нужное в своём проекте в функции YST93xSetMode(uint8_t mode) в условии переключения диапазонов (YST93x_BAND_FM(AM):) методом записи битов: bitWrite(pll_in1[0], IN10_R0,  1) и т.п.

Потом читаем пункт в datasheet Programmable Divider Structure.

Выбор кварца реализован в функции инициализации микросхемы (YST93xInit() ) .

А здесь datasheet по-русски.

s4va
Offline
Зарегистрирован: 11.04.2015

led, день добрый!

Прошу прощение, что не в тему данного форума. Меня интересует приспособление линейного входа к данному аппарату. Если вас не затруднит - не могли бы вы меня направить в правильное русло или точно указать каким образом это можно произвести.

P.S.: в программировании я силен, а вот в радио деле и микроэлектронике совсем слаб. Простите еще раз за офтоп.
 

led
Offline
Зарегистрирован: 04.11.2012

s4va, Смотря как вы хотите реализовать линейный вход, если средствами родного контролёра управления, то не знаю как можно будет задействовать "лишние" входа коммутатора микросхемы tda7439 (а они там есть), если ничего не делать  с родным контролером управления (если вообще можно что сним сделать), то как вариант можно за место "лишнего" функционала (кассета, диски) подключить внешний источник сигнала. Если же заменить родной процессор на ардуино или др. контролер, то тогда можно програмно задействовать еще один стерео вход микросхемы tda7439 (выводы 8 и 13) добавив пару конденсаторов к ним в разрыв, ну и не помешало бы как минимум пару резисторов, коэфициэнт усиления по входам помоему тоже в этой микросхемы можно программно  регулировать. А т.к. вы в программировании силён, я думаю без труда запустите и СD (которого нет в коде приведённые выше).

socknick
Offline
Зарегистрирован: 18.04.2015

Всем здравия!

В продолжении темы по Sanyo CCB. Валялась у меня панелька от автомагнитолы LG TCC8210,

и решил я ее куда-нибудь приспособить (часы, например). Собрана она на LC75833. Долго читал

даташиты, разбирался с протоколом. Много не понятного, но всетаки запустил, как часы, пока без 

использования кнопок. Чисто эксперимента ради. Заметил, что в данной библиотеке адрес надо

указывать задом наперед, т.е. если указан 46Н, как у меня, то надо писать 64Н.

Вот плоды моих экспериметов https://yadi.sk/d/dLvyOGnUgLWpj, может кому-нибудь понадобится.

Сразу оговорюсь - это даже не черновик, а так ноброски.

В планах подключить TEA5767 FM-приемник и задействовать кнопки.