Fm тюнер на Amega328/TEA5767/энкодер/LCD1602. Даунгрейд до Amega8

kolko
Offline
Зарегистрирован: 12.06.2018

Приветствую! Нашел прошивку под ардуино уно и нано для фм тюнера. Все работает без проблем. Но у меня осталась куча Amega8 и я хочу собрать на нем. Собственно во время компиляции ардуинская оболочка материться на строчки кода: PCICR |= (1 << PCIE2); и PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); - кажеться это регистры контроллера и они отличаются. 

Друзья, возможен ли даунгрейд этого кода с сохранением работоспособности? Благодарю за помощь!

/* name      : fm_tea5767_21.ino
   purpose   : FM stereo receiver using Arduino Uno / Arduino Nano and TEA5767
   author    : LZ2WSG Veselin Georgiev
   site      : http://kn34pc.com/construct/lz2wsg_arduino_fm_rx_tea5767.html
   date      : 09-02-2016
   revision  : v1.21
   tnx       : LZ2DVM Desislav Michev, Encho Hristov
   used info : https://youtu.be/WP7kT-ZUa4E
             : http://www.ad7c.com/projects/ad9850-dds-vfo/
  ---------------------------------------------------------------------------------------------------------*/
#include <Wire.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <rotary.h>

LiquidCrystal lcd(12, 13, 7, 6, 5, 4);       // LCD display pins: RS(4), E(6), D4(11), D5(12), D6(13), D7(14)
Rotary r = Rotary(2, 3);                     // encoder pins: CLK, DT

int pin_sw = 8;                              // encoder push button: MANUAL Tune / MEMORY
unsigned char frequencyH = 0;
unsigned char frequencyL = 0;
unsigned int frequencyB;
unsigned int frequency;
unsigned int old_frequency;
unsigned int old_manual_frequency;
double freq_ic = 1;                          // tea5767 frequency
byte ftm;                                    // relative frequency to save in EEPROM: (F - 82.5)[MHz] * 10
unsigned long mls = 0;                       // time variable
unsigned long vr = 0;                        // time variable
unsigned char buf[5];                        // i2c buffer
byte count;                                  // MEMORY counter
byte old_count;                              // MEMORY old state counter
byte button_state = 0;                       // button flag
boolean mode;                                // TUNE [0] or MEMORY [1] mode
byte sm_buf;                                 // signal-meter buffer
byte sm_p;                                   // signal-meter
byte graph [8][8] = {                        // array of symbols for s-meter
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00},  // 1 line
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00},  // 2 lines
  {0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00},  // 3 lines
  {0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x00},  // 4 lines
  {0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00},  // 5 lines
  {0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00},  // 6 lines
  {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00},  // 7 lines
  {0x1F, 0x1F, 0x1B, 0x11, 0x1B, 0x1F, 0x1F, 0x00}   // +
};
//---------------------------------------------------------------------------------------------------------
void setup()
{
  Wire.begin();
  pinMode(pin_sw, INPUT);
  lcd.begin(16, 2);
  for (int k = 0; k < 8; k++)
    lcd.createChar(k, graph[k]);

  lcd.clear();
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();

  if (digitalRead(pin_sw) == LOW) {          // reset default (feel 0xFF (108 MHz) in all cells in EEPROM)
    vr = millis();                           // push 'encoder button' and turn 'power on' over 5 sec
    while (1) {
      if (digitalRead(pin_sw) == HIGH)
        break;
      if ((millis() - vr) > 5500)
        break;
    }
    if ((millis() - vr) > 5000) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" RESET DEFAULT! ");
      for (int i = 0; i < 17; i++)
        EEPROM.write(i, 0xFF);
      delay(2000);
    }
  }
  mode = true;
  count = 1;
  old_count = 1;
  old_frequency = 0;
  old_manual_frequency = 876;
  ftm = EEPROM.read(1);
  frequency = ftm + 825;
  mls = millis();
}
//---------------------------------------------------------------------------------------------------------
void loop()
{
  if (mode) {                                // receiver is in MEMORY mode
    if (count < 1)
      count = 16;
    if (count > 16)
      count = 1;

    if (count != old_count) {
      ftm = EEPROM.read(count);              // read frequency from EEPROM
      frequency = ftm + 825;                 // relative frequency, stored in EEPROM to real frequency * 10
      old_count = count;
    }
  }

  if (frequency != old_frequency) {
    set_freq();
    read_status();
    old_frequency = frequency;
  }

  if ((millis() - mls) < 3000) {             // several readings on the start
    set_freq();
    read_status();
    delay(200);
  }
  tune_mode();
}
//---------------------------------------------------------------------------------------------------------
ISR(PCINT2_vect)                             // encoder events
{
  unsigned char result = r.process();

  if (result) {
    if (result == DIR_CW) {
      if (mode)
        count++;                             // inc MEMORY + 1
      else
        frequency++;                         // inc frequency + 0.1 MHz
    }
    else {
      if (mode)
        count--;                             // dec MEMORY - 1
      else
        frequency--;                         // dec frequency - 0.1 MHz
    }
  }

  if (frequency < 876) frequency = 876;      // lower end of FM band
  if (frequency > 1080) frequency = 1080;    // top end of FM band
}
// --------------------------------------------------------------------------------------------------------
void set_freq()                              // set TEA5767 frequency by i2c bus
{
  frequencyB = 4 * (frequency * 100000 + 225000) / 32768;
  frequencyH = frequencyB >> 8;
  frequencyL = frequencyB & 0xFF;
  Wire.beginTransmission(0x60);
  Wire.write(frequencyH);
  Wire.write(frequencyL);
  Wire.write(0xB0);
  Wire.write(0x10);                          // XTAL 32.768 kHz
  Wire.write(byte(0x00));                    // deemphasis 50 us (Europe and Australia)
  //  Wire.write(byte(0x40));                  // deemphasis 75 us (North America)
  Wire.endTransmission();
}
//---------------------------------------------------------------------------------------------------------
void read_status()                           // read i2c bus: frequency, mono/stereo and signal (agc)
{
  Wire.requestFrom(0x60, 5);
  if (Wire.available()) {
    for (int i = 0; i < 5; i++)
      buf[i] = Wire.read();

    freq_ic = (((buf[0] & 0x3F) << 8) + buf[1]) * 32768 / 4 - 225000;
    lcd.setCursor(0, 0);
    lcd.print("FM ");
    freq_ic = round(freq_ic / 100000);
    lcd.print(freq_ic / 10, 1);
    lcd.print(" MHz  ");

    lcd.setCursor(13, 0);                    // set STEREO/MONO indicator
    if (buf[2] & 0x80)
      lcd.print("[S]");
    else
      lcd.print("[M]");

    lcd.setCursor(3, 1);                     // draw signal-meter bar indicator
    sm_buf = (buf[3] >> 4);
    sm_p = byte(0.6 * sm_buf);
    for (int j = 0; j < sm_p; j++) {
      lcd.setCursor(3 + j, 1);
      if (j < 6)
        lcd.write(byte(j));
      else if (j < 7)
        lcd.write(byte(6));
      else
        lcd.write(byte(7));
    }
    for (int j = sm_p; j < 10; j++)          // blank left spaces
      lcd.print(' ');

    lcd.setCursor(13, 1);                    // signal-meter indicator in a number
    lcd.print('[');
    lcd.print(sm_p);
    lcd.print(']');
  }
}
//---------------------------------------------------------------------------------------------------------
void tune_mode()                             // MEMORY/TUNE (manual) or SAVE mode
{
  if (mode) {
    lcd.setCursor(0, 1);
    if (count < 10)
      lcd.print('0');
    lcd.print(count);
    lcd.print(' ');
  }
  else  {
    lcd.setCursor(0, 1);
    lcd.print("TU ");
  }

  button_state = read_wbutton(pin_sw);       // MEMORY or TUNE (manual) mode
  if (button_state == 1) {
    mode = !mode;
    if (mode) {
      old_manual_frequency = frequency;
      frequency = ftm + 825;
    }
    else
      frequency = old_manual_frequency;
  }

  if ((button_state == 2) && (!mode)) {      // save current TUNE frequency to MEMORY(COUNT)
    ftm = byte(frequency - 825);             // 108.0 MHz - 255 steps * 0,1 MHz = 82.5 MHz
    EEPROM.write(count, ftm);

    lcd.setCursor(0, 1);
    lcd.print("   SAVE to ");
    if (count < 10)
      lcd.print('0');
    lcd.print(count);
    lcd.print("   ");
    delay(2000);
    read_status();
    mode = HIGH;
    old_manual_frequency = frequency;
  }
}
//---------------------------------------------------------------------------------------------------------
int read_wbutton (int pin_wbutton)           // push button state, return: 0(very fast), 1(fast), 2(slow)
{
  unsigned long vreme_start = 0;
  unsigned long vreme_button = 0;
  int wposition = 0;

  vreme_start = millis();
  while (digitalRead(pin_wbutton) == LOW) {
    vreme_button = millis() - vreme_start;
    if (vreme_button > 800)
      break;
  }
  if (vreme_button < 20)                     // 'nothing' for debounce
    wposition = 0;
  else if (vreme_button > 300)               // slow push button
    wposition = 2;
  else wposition = 1;                        // fast push button
  return wposition;
}
//---------------------------------------------------------------------------------------------------------

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А смысл?

Стоимость правки заведомо превышет стоимость уно/нано, не говоря уже о разнице между уно/нано и Атмега8.

kolko
Offline
Зарегистрирован: 12.06.2018

так все серьезно? Хорошо. Можно получить как ответ поразвернутей почему эта правка неоправданна (эта часть кода отвечает за энкодер)

sadman41
Онлайн
Зарегистрирован: 19.10.2016

В принципе там PCINT заводится только для того, чтобы отреагировать на INT0 и INT1. Я бы попытался выкинуть эту инициализацию целиком, а содержание ISR заменить на функцию, которую бы навесил на два attachInterrupt-а. Конечно, если других особенностей, несовместимых с Atmega8, нет у скетча.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

kolko пишет:

так все серьезно? Хорошо. Можно получить как ответ поразвернутей почему эта правка неоправданна (эта часть кода отвечает за энкодер)

В профессиональном программировании одна строка отлаженного кода стоит примерно $12, а плата Arduino Pro Mini - менее $2. Скетч, конечно, это не профессиональное программирование, но и то, что выходит за рамки унификации Ардуино (т.е. специфика 8 по сравнению с 328) тоже уже не совсем скетч.