Fm тюнер на Amega328/TEA5767/энкодер/LCD1602. Даунгрейд до Amega8
- Войдите на сайт для отправки комментариев
Втр, 12/06/2018 - 16:35
Приветствую! Нашел прошивку под ардуино уно и нано для фм тюнера. Все работает без проблем. Но у меня осталась куча 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; } //---------------------------------------------------------------------------------------------------------
А смысл?
Стоимость правки заведомо превышет стоимость уно/нано, не говоря уже о разнице между уно/нано и Атмега8.
так все серьезно? Хорошо. Можно получить как ответ поразвернутей почему эта правка неоправданна (эта часть кода отвечает за энкодер)
В принципе там PCINT заводится только для того, чтобы отреагировать на INT0 и INT1. Я бы попытался выкинуть эту инициализацию целиком, а содержание ISR заменить на функцию, которую бы навесил на два attachInterrupt-а. Конечно, если других особенностей, несовместимых с Atmega8, нет у скетча.
так все серьезно? Хорошо. Можно получить как ответ поразвернутей почему эта правка неоправданна (эта часть кода отвечает за энкодер)
В профессиональном программировании одна строка отлаженного кода стоит примерно $12, а плата Arduino Pro Mini - менее $2. Скетч, конечно, это не профессиональное программирование, но и то, что выходит за рамки унификации Ардуино (т.е. специфика 8 по сравнению с 328) тоже уже не совсем скетч.