WI-FI интернет радио.

10427 ответов [Последнее сообщение]
obuhanoe
Offline
Зарегистрирован: 18.05.2016

Считал, что если мощные колонки, то нужно приминять усилитель типа PAM.

samand587
Offline
Зарегистрирован: 21.02.2020

Интернет радио это ЕСП + декодер( делают и без него), а усилитель это доп. опция. Усилитель можете любой какой есть в наличии. 

obuhanoe
Offline
Зарегистрирован: 18.05.2016

samand587 пишет:

Интернет радио это ЕСП + декодер( делают и без него), а усилитель это доп. опция. Усилитель можете любой какой есть в наличии. 

Получается любую ESP + VS1053b?
Если колонки слабенькие 2*2,5Вт - усилитель не нужен, а если Ватт на 30 то любой верно?

obuhanoe
Offline
Зарегистрирован: 18.05.2016

samand587 пишет:

Посмотрите в эту https://4pda.to/forum/index.php?showtopic=1010378&st=1880#entry112992611  сторону  Это лучше!

 

З.Ы. Колонки никак не влияют на конфигурацию интернет радио!

Что именно на это странице смотреть, на определенное сообщение не переходит, открывает страницу 95.

samand587
Offline
Зарегистрирован: 21.02.2020

obuhanoe пишет:
...Что именно на это странице смотреть,...

 

Тогда вот https://github.com/e2002/yoradio/

Усилитель нужен, декодер тянет только наушники.

Применение конкретной модификации ЕСП и декодера смотреть в описании радио.

obuhanoe
Offline
Зарегистрирован: 18.05.2016

samand587 пишет:

obuhanoe пишет:
...Что именно на это странице смотреть,...

 

Тогда вот https://github.com/e2002/yoradio/

Усилитель нужен, декодер тянет только наушники.

Применение конкретной модификации ЕСП и декодера смотреть в описании радио.

А чем по Вашему ё-радио лучше Карадио?

Спасибо

ShAlex13
Offline
Зарегистрирован: 19.01.2018

obuhanoe пишет:

А чем по Вашему ё-радио лучше Карадио?

По мне так, тот же х.. только сбоку,

перепробовал разные радио на ESP-хах и перешел на Raspberry, и ни сколько не жалею.

obuhanoe
Offline
Зарегистрирован: 18.05.2016

ShAlex13 пишет:

obuhanoe пишет:

А чем по Вашему ё-радио лучше Карадио?

По мне так, тот же х.. только сбоку,

перепробовал разные радио на ESP-хах и перешел на Raspberry, и ни сколько не жалею.

Сбоку так сбоку ))))

Дома кстати да можно и на raspberry - какой проект посоветуете? нужны дополнительные детали кроме самой rasp ?

 

На даче однозначно на ESP придется делать - почитал про все проекты глаза разбегаются и каша такая наваристая в голове ))))

samand587
Offline
Зарегистрирован: 21.02.2020

obuhanoe пишет:
...А чем по Вашему ё-радио лучше Карадио?...

Соберите и то и другое! Сравните и увидите...

 

ShAlex13
Offline
Зарегистрирован: 19.01.2018

obuhanoe пишет:

Дома кстати да можно и на raspberry - какой проект посоветуете? нужны дополнительные детали кроме самой rasp ?

Юзаю такой, без экрана

https://www.youtube.com/watch?v=E05Tk5XyVgA

Romanz
Offline
Зарегистрирован: 28.09.2019

Ёрадио лучше в поддержке и разнообразии железок, есть плагины, прошивка автором постоянно пилится, есть обратная связь с автором на 4пда. Но карадио легче установить\прошить. С Ёрадио в этом плане посложнее. Но Ёрадио на равнозначном железе играет постабильнее и те ссылки, что карадио не берет. 

obuhanoe
Offline
Зарегистрирован: 18.05.2016

samand587 пишет:

obuhanoe пишет:
...А чем по Вашему ё-радио лучше Карадио?...

Соберите и то и другое! Сравните и увидите...

 

 

Прошить я думаю с этим у меня проблем, не будет.

Вопрос только в том, какие железки из китая заказать, сейчас у меня в наличии есть только esp8266 и esp32.

obuhanoe
Offline
Зарегистрирован: 18.05.2016

ShAlex13 пишет:

obuhanoe пишет:

Дома кстати да можно и на raspberry - какой проект посоветуете? нужны дополнительные детали кроме самой rasp ?

Юзаю такой, без экрана

https://www.youtube.com/watch?v=E05Tk5XyVgA

Правильно я понял, что volumio нельзя поставить в виде программы на существующую ОС?

У меня raspberry выполняет определенные задачи и сносить текущую ОС нельзя. Значит такой вариант мне не подходит, но за совет спасибо.

samand587
Offline
Зарегистрирован: 21.02.2020

obuhanoe пишет:
...какие железки из китая заказать...

Вы сначала определитесь с радио, а потом закажете железки Здесь https://4pda.to/forum/index.php?showtopic=1010378&st=3180 в шапке разнообразие радио. Какое выберите то и закажете

obuhanoe
Offline
Зарегистрирован: 18.05.2016

samand587 пишет:

obuhanoe пишет:
...какие железки из китая заказать...

Вы сначала определитесь с радио, а потом закажете железки Здесь https://4pda.to/forum/index.php?showtopic=1010378&st=3180 в шапке разнообразие радио. Какое выберите то и закажете

Понял, останавлюсь на Карадио и ЁРадио. От этого и буду плясать.

Спасибо.

CyberVad
Offline
Зарегистрирован: 30.07.2018

Добрый день!
Меня вроде не забанили в гугле, но я с трудом нашёл ссылку на гитхаб ё-радио ( https://github.com/e2002/yoradio#connection-tables ), и ни одной с какими то пояснениями. Кто нибудь даст ссылку? Или разъяснит:
1. Это компилируется, заливается в Ардуино?
2. Что надо установить в Ардуино что бы это заработало? Я скинул библиотеку(ли?) arduino-esp32-master туда где все ардуиновские библиотеки
Спасибо

samand587
Offline
Зарегистрирован: 21.02.2020

CyberVad пишет:
... Кто нибудь даст ссылку? ....

Вот https://4pda.to/forum/index.php?showtopic=1010378&st=1880#entry112992611 Все предельно ясно расписано

З.Ы. Ссылки выше приводил- лень открыть? 

CyberVad
Offline
Зарегистрирован: 30.07.2018

Папаша, полегче

samand587
Offline
Зарегистрирован: 21.02.2020

И что? Где картинка работы радио? То что Вы сделали это начало пути!

CyberVad
Offline
Зарегистрирован: 30.07.2018

Залил, прошил, вышил - а по адресу 192.168.4.1 нет страницы. Точка доступа - есть.
Что бы предпринять?

CyberVad
Offline
Зарегистрирован: 30.07.2018

Кстати, прошивка заливается, без ошибок, и после сообщения:

Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32-master: C:\Program Files\Arduino\libraries\arduino-esp32-master
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1: C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32-master: C:\Program Files\Arduino\libraries\arduino-esp32-master
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1: C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1
 Какая библиотека? И почему ардуино вспомнил после загрузки?..
ShAlex13
Offline
Зарегистрирован: 19.01.2018

CyberVad пишет:

Залил, прошил, вышил - а по адресу 192.168.4.1 нет страницы. Точка доступа - есть.
Что бы предпринять?

Смотри лог, там все пишется

CyberVad
Offline
Зарегистрирован: 30.07.2018

"Учите матчасть" говорите... О чём говорит вот этот лог: 

esptool.py v3.0-dev
Serial port COM3
Connecting......
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 40:91:51:bc:ed:24
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 4369.0 kbit/s)...
Hash of data verified.
Compressed 18656 bytes to 12053...
Writing at 0x00001000... (100 %)
Wrote 18656 bytes (12053 compressed) at 0x00001000 in 0.2 seconds (effective 956.7 kbit/s)...
Hash of data verified.
Compressed 1190768 bytes to 709501...
Writing at 0x00010000... (2 %)
Writing at 0x00014000... (4 %)
Writing at 0x00018000... (6 %)
Writing at 0x0001c000... (9 %)
Writing at 0x00020000... (11 %)
Writing at 0x00024000... (13 %)
Writing at 0x00028000... (15 %)
Writing at 0x0002c000... (18 %)
Writing at 0x00030000... (20 %)
Writing at 0x00034000... (22 %)
Writing at 0x00038000... (25 %)
Writing at 0x0003c000... (27 %)
Writing at 0x00040000... (29 %)
Writing at 0x00044000... (31 %)
Writing at 0x00048000... (34 %)
Writing at 0x0004c000... (36 %)
Writing at 0x00050000... (38 %)
Writing at 0x00054000... (40 %)
Writing at 0x00058000... (43 %)
Writing at 0x0005c000... (45 %)
Writing at 0x00060000... (47 %)
Writing at 0x00064000... (50 %)
Writing at 0x00068000... (52 %)
Writing at 0x0006c000... (54 %)
Writing at 0x00070000... (56 %)
Writing at 0x00074000... (59 %)
Writing at 0x00078000... (61 %)
Writing at 0x0007c000... (63 %)
Writing at 0x00080000... (65 %)
Writing at 0x00084000... (68 %)
Writing at 0x00088000... (70 %)
Writing at 0x0008c000... (72 %)
Writing at 0x00090000... (75 %)
Writing at 0x00094000... (77 %)
Writing at 0x00098000... (79 %)
Writing at 0x0009c000... (81 %)
Writing at 0x000a0000... (84 %)
Writing at 0x000a4000... (86 %)
Writing at 0x000a8000... (88 %)
Writing at 0x000ac000... (90 %)
Writing at 0x000b0000... (93 %)
Writing at 0x000b4000... (95 %)
Writing at 0x000b8000... (97 %)
Writing at 0x000bc000... (100 %)
Wrote 1190768 bytes (709501 compressed) at 0x00010000 in 13.7 seconds (effective 697.1 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 129...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (129 compressed) at 0x00008000 in 0.0 seconds (effective 1536.0 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32-master: C:\Program Files\Arduino\libraries\arduino-esp32-master
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1: C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32-master: C:\Program Files\Arduino\libraries\arduino-esp32-master
Неверная библиотека найдена в C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1: C:\Program Files\Arduino\libraries\arduino-esp32fs-plugin-0.1

 

CyberVad
Offline
Зарегистрирован: 30.07.2018

Вот лог из ЕСП

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4


Running in AP mode.
Connect to AP yoRadioAP with password 12345987 for settings.

-шки

CyberVad
Offline
Зарегистрирован: 30.07.2018

Следующие нелицеприятные вопросы.
Вот есть дисплей ILI9341. Я копирую файл myoptions.h в корень проекта. Запускаю yoRadio.ino. Вижу в множестве вкладок и myoptions.h . Хорошо. Проект принял во внимание его. Я это так подробно описываю что бы минимизировать вопросы неравнодушных читателей. Далее редактирую - самое простое - 
#define DSP_MODEL         DSP_DUMMY
на 
#define DSP_MODEL         9
Получаем

Alternatives for Adafruit_I2CDevice.h: []
ResolveLibrary(Adafruit_I2CDevice.h)
  -> candidates: []In file included from D:\Projects\YoRadio\yoradio-main\yoRadio\src\displays\displayILI9341.h:5:0,

                 from D:\Projects\YoRadio\yoradio-main\yoRadio\display.h:26,
                 from D:\Projects\YoRadio\yoradio-main\yoRadio\yoRadio.ino:10:
C:\Program Files\Arduino\libraries\Adafruit-GFX-Library-master/Adafruit_GFX.h:12:32: fatal error: Adafruit_I2CDevice.h: No such file or directory
compilation terminated.

А ведь на гитхубе написано "просто редактируем myoptions.h"
Я понимаю что на заборе тоже много чего разного пишут, ну а правильно как?

samand587
Offline
Зарегистрирован: 21.02.2020

Adafruit_I2CDevice.h: No such file or directory

Вот ответ на Ваш вопрос. Ставьте правильные библиотеки!

CyberVad
Offline
Зарегистрирован: 30.07.2018

Далее. "Ставьте правильные библиотеки". Поставил. Залилось. Дисплей заработал, правда на дисплее мы наблюдаем "FRADIO" (F отражена слева на право), ну да ладно. Но по адресу 192.168.4.1 по прежнему ничего нет ! Чертовщина какая то. Может ещё что то куда то скопировать, настроить?
 

ShAlex13
Offline
Зарегистрирован: 19.01.2018

Точка доступа появляется? Если есть, подключаемся.

CyberVad
Offline
Зарегистрирован: 30.07.2018

Есть, как не быть, но по адресу тому ничего, ни-че-го нет. Вот совсем

ShAlex13
Offline
Зарегистрирован: 19.01.2018

CyberVad пишет:

Есть, как не быть, но по адресу тому ничего, ни-че-го нет. Вот совсем

а попробовать 192.168.4.2 или 3 или 4

CyberVad
Offline
Зарегистрирован: 30.07.2018

Да я вчера смотрел, шлюз .1 
Ну попробовал, никого.

Ещё все так "быстро"... Минут 10-15 проходит с того момента как нажал стрелочку до загрузки... Успеваешь и забыть что поменял...

samand587
Offline
Зарегистрирован: 21.02.2020

А Вы делали ESP32 Sketch Data Upload?

CyberVad
Offline
Зарегистрирован: 30.07.2018

Вот отдельно нажать "ESP32 Sketch Data Upload"? Да. Но и тупо нажать стрелочку в ардуино прошивает именно то. Сейчас подменил файл шрифта, как написано. Нажал стрелочку. И вот пожалуйста - "ёRADIO" бежит в верхней сроке дисплея
Может это ESP32 калечные? Надо (дома) взять заведомо исправную (на ней сейчас работает КаРадио) Но практика показывает что это не то, это было бы слишком просто... Кстати, это ничего что я прошиваю просто ESP32 подключенную к компу и дисплей?

ShAlex13
Offline
Зарегистрирован: 19.01.2018

CyberVad пишет:

Да я вчера смотрел, шлюз .1 
Ну попробовал, никого.

А с телефона зайти?

samand587
Offline
Зарегистрирован: 21.02.2020

Очистите полностью ESP32, прошейте скетч, перезагрузите Ардуино и плату, сделайте ESP32 Sketch Data Upload и почитайте рекомендации https://4pda.to/forum/index.php?showtopic=1010378&st=1880#entry112992611

CyberVad
Offline
Зарегистрирован: 30.07.2018

/sites/default/files/u39745/resize_of_20220722_131149_resized.jpg

Смотрел я сцылку на 4пда, и следующих страниц 10-15...

ShAlex13
Offline
Зарегистрирован: 19.01.2018

CyberVad пишет:

/sites/default/files/u39745/resize_of_20220722_131149_resized.jpg

Смотрел я сцылку на 4пда, и следующих страниц 10-15...

А если запитать ESP-ху нормально, а не от "черной изоленты" ?

CyberVad
Offline
Зарегистрирован: 30.07.2018

Похоже вы правы, но точка доступа же есть!...
Пока всем спасибо

CyberVad
Offline
Зарегистрирован: 30.07.2018

Хотели как лучше... 
Я хотел на скорую руку собрать, проверить софт, смогу ли компилить и тп.
Теперь ясно, что дело стоящее, надо делать плато

 /sites/default/files/u39745/20220722_143311_resized.jpg

Не знаю почему вместо картинок ссылки...

ShAlex13
Offline
Зарегистрирован: 19.01.2018

CyberVad пишет:

Хотели как лучше... 

Ну дак и что было? Почему не цеплялся к 192.168.4.1 ?

CyberVad
Offline
Зарегистрирован: 30.07.2018

Старо как мир. Конденсатор выпаяный с материнки 3300мкФ помог. Позор мне...

ShAlex13
Offline
Зарегистрирован: 19.01.2018

CyberVad пишет:

Старо как мир. Конденсатор выпаяный с материнки 3300мкФ помог. Позор мне...

По статистике 99% косяков из-за "не правильного" питания...

pilnikov
pilnikov аватар
Offline
Зарегистрирован: 28.08.2015

CyberVad пишет:

Старо как мир. Конденсатор выпаяный с материнки 3300мкФ помог. Позор мне...

не удержался, вспомнил.....

alexeko
Offline
Зарегистрирован: 03.01.2014

Всем доброго дня. Делюсь очередной сборкой. Работает, на удивление ОТЛИЧНО, без шумов, помех и т.п. побочки.

Собрал на TTGO Tm  2,4 дюймов PCM5102A SD карта MCU32 WiFi + Bluetooth модуль + выносная антенна

Запитал TTGO через  B0505S-2W DIP-4 DC-DC 

. 

Усилитель - Модуль PAM8403, плата цифрового усилителя, 2*3 Вт

Энкодер с резисторами 10 кОм, плохо заработал, а вот с 9 кОм просто отлично, Сам не знаю почему так, не спрашивайте.

Схема сборки энкодера

Проект брал ТУТ и вторая ЧАСТЬ. Динамики вытащил из компьютерной акустики за 400р в ДНС (они там, как оказалось, в моно режиме работали).

 

smax2004
Offline
Зарегистрирован: 11.09.2021

Добрый вечер. Может кто нибудь помочь победить OLED 2.42 дисплей? Приехал этот зверь с алиэкспресс , третий день сижу над ния , не могу запустить. На ESP32 маленький дисплей работает по I2C,этот не хочет. Подключил по SPI  то же тишина. Подключал этот дисплей для проверки к меге 2560  по spi -test работает. по I2C- не получилось. Перемычки на дисплее перепаивал ничего не даёт. Как  правильно подключить OLED 2.42 и ESP32 ??? Менял типы дисплеев sys.lcd("x") Подставлял 0,1,2,3  - ни на что не влияет.
Соединял   CS-D3  DC-14  RES-D2  SDA-23 CSL-18 vcc-3.3 GND-GND.

Модуль OLED 2.42  IC I2C SPI SSD 1309  128x64  
(https://aliexpress.ru/item/1005003603707824.html?spm=a2g2w.orderdetails.0.0.35db4aa6RAksin&sku_id=12000026685159628&_ga=2.76692374.2039569106.1664993738-690865407.1653937290)

Плата ESP32-WROOM-32U  36pin
(
https://aliexpress.ru/item/4000093185394.html?spm=a2g2w.orderdetails.0.0.224e4aa6Ydu4BU&sku_id=12000017405089025&_ga=2.244004870.2039569106.1664993738-690865407.1653937290)

Может файл конфигурации какой то нужен особый.
Прошивка с проекта Karadio32 R2.3  (karawin/Ka-Radio32)

 

alexeko
Offline
Зарегистрирован: 03.01.2014

smax2004 пишет:

Может кто нибудь помочь победить OLED 2.42 дисплей? 

Я бы, посоветовал прикрутить его через Ардуинку по UART. Я так подключал, а за одно и кнопки сделал. Всё управление идет по ПОРТУ. 

Я ВОТ ТАКОЙ подключал

samand587
Offline
Зарегистрирован: 21.02.2020


Задам вопрос здесь. Где в этом скетче регулируется контрастность дисплея? Спасибо!


#include <SoftwareSerial.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <IRremote.h>
#include <TEA5767N.h>
#include <Evc_pt2257.h>
#include <MemoryFree.h>
#include <DS3231.h>
#include <AT24CX.h>

#define APP_STATE_MAIN                0
#define APP_STATE_MENU                1
#define APP_STATE_SEARCH              2
#define APP_STATE_FINE_SEARCH         3
#define APP_STATE_REGISTER            4
#define APP_STATE_CONFIG              5
#define APP_STATE_STANDBY             6
#define APP_STATE_DEFAULTS            7
#define APP_STATE_CONFIG_SEARCH_LEVEL 8
#define APP_STATE_EXTRA_INFO          9

#define MENU_MAIN_SEARCH      0
#define MENU_MAIN_FINE_SEARCH 1
#define MENU_MAIN_REGISTER    2
#define MENU_MAIN_CONFIG      3
#define MENU_MAIN_DEFAULTS    4

#define MENU_CONFIG_SEARCH_LEVEL 0

#define EEPROM_STATION_MARKER          0
#define EEPROM_STATION_INT             1
#define EEPROM_STATION_FLOAT           2
#define EEPROM_SEARCH_LEVEL_MARKER     3
#define EEPROM_SEARCH_LEVEL            4
#define EEPROM_VOLUME_MARKER           5
#define EEPROM_VOLUME                  6
#define EEPROM_DEFAULT_STATIONS_MARKER 7
#define EEPROM_DEFAULT_STATIONS        8

#define EEPROM_STATION_MARKER_VALUE          111
#define EEPROM_SEARCH_LEVEL_MARKER_VALUE     112
#define EEPROM_VOLUME_MARKER_VALUE           113
#define EEPROM_DEFAULT_STATIONS_MARKER_VALUE 114

#define FREQ_MIN 88.0
#define FREQ_MAX 108.0

#define VOLUME_STEP 4
#define VOLUME_MUTE_STEP 56
#define VOLUME_MUTE 79

#define RECV_PIN 12
#define LCD_BACKLIGHT_PIN 9

Adafruit_PCD8544 display = Adafruit_PCD8544(13, 11, 2, 4, 3);
TEA5767N radio = TEA5767N();
IRrecv irrecv(RECV_PIN);
AT24CX mem;
DS3231 clock;
RTCDateTime dt;
decode_results results;

#define STATION_COUNT 20
#define MENU_MAIN_LINES 5
#define MENU_CONF_LINES 1
#define MENU_SEARCH_LEVEL_LINES 3

const char mainMenu_1[] PROGMEM = "Search";
const char mainMenu_2[] PROGMEM = "Fine search";
const char mainMenu_3[] PROGMEM = "Register st.";
const char mainMenu_4[] PROGMEM = "Config";
const char mainMenu_5[] PROGMEM = "Default st.";

const char* const mainMenu[] PROGMEM =
{   mainMenu_1, mainMenu_2, mainMenu_3, mainMenu_4, mainMenu_5};

const char confMenu_1[] PROGMEM = "Search level";

const char* const confMenu[] PROGMEM =
{   confMenu_1};

const char searchLevelMenu_1[] PROGMEM = "Low";
const char searchLevelMenu_2[] PROGMEM = "Medium";
const char searchLevelMenu_3[] PROGMEM = "High";

const char* const searchLevelMenu[] PROGMEM =
{   searchLevelMenu_1, searchLevelMenu_2, searchLevelMenu_3};

// Predefined stations array
const char stationName_1[] PROGMEM = "BAJKA";
const char stationName_2[] PROGMEM = "NOSTALGIA";
const char stationName_3[] PROGMEM = "WAWA";
const char stationName_4[] PROGMEM = "RMF FM";
const char stationName_5[] PROGMEM = "ESKA ROCK";
const char stationName_6[] PROGMEM = "ZET GOLD";
const char stationName_7[] PROGMEM = "RMF MAXXX";
const char stationName_8[] PROGMEM = "PLUS";
const char stationName_9[] PROGMEM = "KAMPUS";
const char stationName_10[] PROGMEM = "TOK FM";
const char stationName_11[] PROGMEM = "RMF CLASSIC";
const char stationName_12[] PROGMEM = "ZLOTE PRZEBOJE";
const char stationName_13[] PROGMEM = "ZET CHILLI";
const char stationName_14[] PROGMEM = "MUZO.FM";
const char stationName_15[] PROGMEM = "KOLOR";
const char stationName_16[] PROGMEM = "ROCK";
const char stationName_17[] PROGMEM = "VOX FM";
const char stationName_18[] PROGMEM = "ESKA";
const char stationName_19[] PROGMEM = "ANTYRADIO";
const char stationName_20[] PROGMEM = "ZET";

const char* const stationName[] PROGMEM =
{
    stationName_1,
    stationName_2,
    stationName_3,
    stationName_4,
    stationName_5,
    stationName_6,
    stationName_7,
    stationName_8,
    stationName_9,
    stationName_10,
    stationName_11,
    stationName_12,
    stationName_13,
    stationName_14,
    stationName_15,
    stationName_16,
    stationName_17,
    stationName_18,
    stationName_19,
    stationName_20
};

//TODO move to flash
float defaultStations[STATION_COUNT] = { 87.8,   //Bajka
        88.4,   //Nostalgia
        89.8,   //WAWA
        90.6,   //RMF FM
        93.3,   //ESKA Rock
        94.0,   //ZET Gold
        95.8,   //RMF Maxxx
        96.5,   //Plus
        97.1,   //Kampus
        97.7,   //Tok FM
        98.3,   //RMF Classic
        100.1,   //Złote przeboje
        101.5,   //ZET Chilli
        102.0,   //MUZO.FM
        103.0,   //Kolor
        103.7,   //Rock
        104.4,   //Vox FM
        105.6,   //ESKA
        106.8,   //Antyradio
        107.5   //ZET
        };

// Initialized station arrays
float stations[STATION_COUNT] = {
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0 };

char buffer[20];

// Is radio on?
boolean radioOn = false;

// Displaying names for loaded default stations
boolean defaultStationsFlag = true;

// Keep the current station index
byte stationIndex = 0;

// Index of the menu item currently selected
byte selectedMenuItem = 0;

// Level required to search
byte searchLevel;

// This variable helps to keep track of the buttons state:
// the command for a pressed button is only accepted if
// previously it was in  not pressed state
boolean buttonWasReleased = true;

// Keep the application state where the execution
// is trapped so a specific set of menu items is shown to the user
byte applicationState = 0;

// Used for fine search commands
float selectedStation;

// Current volume level
uint8_t volume = 0;

// Load the station stored in the EEPROM static memory
void loadStation() {
    byte markerCode, intStation, floatStation;
    float station;

    markerCode = mem.read(EEPROM_STATION_MARKER);

    if (markerCode == EEPROM_STATION_MARKER_VALUE) {
        intStation = mem.read(EEPROM_STATION_INT);
        floatStation = mem.read(EEPROM_STATION_FLOAT);
        station = (intStation * 1.0) + (floatStation * .1);
        Serial.print(F("freq from eeprom: "));
        Serial.println(station, 1);
        radio.selectFrequency(station);
        stationIndex = findSelectedStationIndex(station);
    } else {
        radio.selectFrequency(stations[stationIndex]);
    }
}

byte findSelectedStationIndex(float station) {
    for (int i = 0; i < STATION_COUNT; i++) {
        if (stations[i] == station) {
            return i;
        }
    }
    return 0;
}

void displayData(const __FlashStringHelper *msg) {
    char freq[5];
    byte sl;

    dtostrf(radio.readFrequencyInMHz(), 1, 1, freq);
    sl = radio.getSignalLevel() / 2;   //max 15/2

    display.clearDisplay();
    display.setTextColor(BLACK);
    display.setTextSize(1);
    display.setTextWrap(false);
    display.setCursor(0, 0);
    display.println(msg);
    display.setCursor(0, display.getCursorY() + 5);
    display.setTextSize(2);

    RTCDateTime dt = clock.getDateTime();

    if (getDefaultStationsFlag()
            && ((dt.second % 5 == 0) || (dt.second % 5 == 1))) {
        display.print(dt.hour);
        display.print(F(":"));
        if (dt.minute < 10) {
            display.print(F("0"));
        }
        display.print(dt.minute);
        display.println();
    } else {
        display.println(freq);
    }

    // draw a signal level triangle
    display.drawTriangle(0, 47, 0, 39, 14, 47, BLACK);
    // draw a signal level
    for (int x = 0; x < sl; x++) {
        display.drawLine(14 - 2 * x, 47, 14 - 2 * x, 47 - x, BLACK);
    }

    // draw the antena
    display.drawLine(18, 39, 18, 46, BLACK);   //pionowa
    display.drawLine(14, 39, 18, 43, BLACK);   //lewa antenka
    display.drawLine(22, 39, 18, 43, BLACK);   //prawa antenka

    // draw a volume level triangle
    display.drawTriangle(69, 47, 83, 39, 83, 47, BLACK);
    /**
     * max value 56 with step 4 gives 14 level
     * result is divided by 2 because lcd show 7 levels
     *
     * 56/8 => 7   (7)
     * 52/8 => 6.5 (7)
     * 48/8 => 6   (6)
     * 44/8 => 5.5 (6)
     * itd.
     */
    // draw volume level
    for (int x = 0; x < 7 - ceil(volume / 8); x++) {
        display.drawLine(69 + 2 * x, 47, 69 + 2 * x, 47 - x, BLACK);
    }

    // draw speaker icon
    display.drawRect(58, 40, 3, 4, BLACK);
    display.drawLine(61, 40, 64, 37, BLACK);
    display.drawLine(61, 44, 64, 47, BLACK);
    display.drawLine(64, 37, 64, 47, BLACK);
    // draw mute
    if (radio.isMuted()) {
        display.drawLine(57, 46, 66, 37, BLACK);
    }

    display.setCursor(34, 38);
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);

    if (radio.isStereo()) {
        display.println(F("ST"));
    } else {
        display.println(F("MN"));
    }

    display.display();
}

void displayDataWithMsg(const __FlashStringHelper *msg) {
    displayData(msg);
}

void displayDefaultData() {
    if (getDefaultStationsFlag()) {
        displayData(
                (const __FlashStringHelper *) pgm_read_word(
                        &(stationName[stationIndex])));
    } else {
        displayData(F(""));
    }
}

// Load the search level stored in the EEPROM static memory
void loadSearchLevel() {
    byte marker = mem.read(EEPROM_SEARCH_LEVEL_MARKER);

    if (marker == EEPROM_SEARCH_LEVEL_MARKER_VALUE) {
        searchLevel = mem.read(EEPROM_SEARCH_LEVEL);
        /*Serial.print(F("SearchLevel from eeprom: "));
         Serial.println(searchLevel);*/
    } else {
        searchLevel = MID_STOP_LEVEL;
    }

    searchLevel = MID_STOP_LEVEL;

    switch (searchLevel) {
        case LOW_STOP_LEVEL: {
            //Serial.println("Load LOW_STOP_LEVEL");
            radio.setSearchLowStopLevel();
            break;
        }
        case MID_STOP_LEVEL: {
            //Serial.println("Load MID_STOP_LEVEL");
            radio.setSearchMidStopLevel();
            break;
        }
        case HIGH_STOP_LEVEL: {
            //Serial.println("Load HIGH_STOP_LEVEL");
            radio.setSearchHighStopLevel();
            break;
        }
    }
}

void loadVolume() {
    byte marker = mem.read(EEPROM_VOLUME_MARKER);

    if (marker == EEPROM_VOLUME_MARKER_VALUE) {
        volume = mem.read(EEPROM_VOLUME);
        Serial.print(F("Volume from eeprom: "));
        Serial.println(volume);
        evc_setVolume((uint8_t) volume);
    }
}

void loadDefaultStationsFlag() {
    byte marker = mem.read(EEPROM_DEFAULT_STATIONS_MARKER);

    if (marker == EEPROM_DEFAULT_STATIONS_MARKER_VALUE) {
        defaultStationsFlag = mem.read(EEPROM_DEFAULT_STATIONS);
        Serial.print(F("Read default stations from eeprom: "));
        Serial.println(defaultStationsFlag);
    } else {
        defaultStationsFlag = false;
    }
}

boolean getDefaultStationsFlag() {
    return defaultStationsFlag;
}

/**
 * Saves the station passed as parameter in the EEPROM
 * The station is stored in two parts
 */
void saveStation(float station) {
    //Serial.print(F("save station: "));
    //Serial.println(station);

    float aux;
    byte byteValue = (byte) floor(station);

    mem.write(EEPROM_STATION_MARKER, EEPROM_STATION_MARKER_VALUE);
    delay(10);
    mem.write(EEPROM_STATION_INT, byteValue);
    delay(10);
    aux = station - floor(station);
    aux *= 10.0;
    if (aux > 5.0) {
        byteValue = byte(aux);
        if ((((float) byteValue) - aux) > 0.1) {
            byteValue--;
        } else if ((aux - ((float) byteValue)) > 0.1) {
            byteValue++;
        }
    } else {
        byteValue = (int) ceil(aux);
    }
    mem.write(EEPROM_STATION_FLOAT, byteValue);
    delay(10);
}

void radioLoadConfig() {
    radio.mute();
    loadDefaultStations();
    loadDefaultStationsFlag();
    loadStation();
    loadSearchLevel();
    loadVolume();
}

void loadDefaultStations() {
    for (int i = 0; i < STATION_COUNT; i++) {
        stations[i] = defaultStations[i];
    }
}

void setup() {
    Serial.begin(9600);
    irrecv.enableIRIn(); //Start the receiver

    while (!Serial) {
        // wait for serial port to connect. Needed for native USB port only
    }
    evc_init();
    clock.begin();
    clock.setDateTime(__DATE__, __TIME__);
    //Serial.println(F("Starting radio ... "));

    display.begin();
    display.setContrast(40);
    display.display();
    delay(50);
    display.clearDisplay();

    radioLoadConfig();
    radio.setSoftMuteOn();
    radio.setHighCutControlOn();
    radio.setStandByOn();
    setApplicationState(APP_STATE_STANDBY);
}

void btnPower() {
    if (!buttonWasReleased)
        return;

    buttonWasReleased = false;

    if (radio.isStandBy()) {
        //Necessary to eliminate noise while turning the radio back on
        radio.mute();
        //loadStation();
        radio.setStandByOff();
        //Necessary to eliminate noise while turning the radio back on
        delay(150);
        radio.turnTheSoundBackOn();
        evc_mute(false);
        pinMode(LCD_BACKLIGHT_PIN, OUTPUT);
        analogWrite(LCD_BACKLIGHT_PIN, 255);
        setApplicationState(APP_STATE_MAIN);
    } else {
        setApplicationState(APP_STATE_STANDBY);
        display.clearDisplay();
        display.display();
        pinMode(LCD_BACKLIGHT_PIN, OUTPUT);
        analogWrite(LCD_BACKLIGHT_PIN, 0);
        radio.setStandByOn();
        evc_mute(true);
    }
}

// The buttons were scanned and none were pressed
void defaultActions() {
    if (!buttonWasReleased) {
        buttonWasReleased = true;
    }

// Since no button was pressed, takes to update some states
    switch (applicationState) {
        case APP_STATE_MAIN:
            displayDefaultData();
            break;
        case APP_STATE_EXTRA_INFO:
            //lcdDateAndTempInfo();
            break;
    }
}

int ii = 0;
unsigned long lastButtonCode;
uint8_t lastNumericButton = 10; //default value for empty variable
uint8_t newNumericButton = 10; //default value for empty variable
unsigned long lastNumericButtonTime = millis();
const int timeoutDelay = 1500; //1,5s

void loop() {
    unsigned long irCode;
    uint8_t numericButton = 10;
    ii++;

    if (ii > 500) {
        ii = 0;
        Serial.print(F("freeMemory()="));
        Serial.println(freeMemory());
    }

    if (irrecv.decode(&results)) {

        //Serial.print(F("selected key: "));

        irCode = results.value;

        if (irCode == 0xFFFFFFFF) {
            //repeated button
            irCode = lastButtonCode;
        } else {
            lastButtonCode = irCode;
        }

        switch (irCode) {
            case 0xFFA25D:
            case 0xE318261B:
                //Serial.print(F("IR_KEY_POWER"));
                btnPower();
                break;
            case 0xFFE01F:
                //Serial.print(F("PREVIOUS"));
                btnPrev();
                break;
            case 0xFF906F:
            case 0xE5CFBD7F:
                //Serial.print(F("NEXT"));
                btnNext();
                break;
            case 0xFFE21D:
            case 0xEE886D7F:
                //Serial.print(F("IR_KEY_MENU"));
                btnMenu();
                break;
            case 0xFF02FD:
            case 0xD7E84B1B:
                // Serial.print(F("IR_KEY_PLUS"));
                btnPlus();
                break;
            case 0xFF9867:
            case 0x97483BFB:
                // Serial.print(F("IR_KEY_MINUS"));
                btnMinus();
                break;
            case 0xFFC23D:
            case 0x20FE4DBB:
                //Serial.print(F("IR_KEY_EXIT"));
                btnExit();
                break;
            case 0xFF22DD:
            case 0x52A3D41F:
                //Serial.print(F("IR_KEY_TEST"));
                btnTest();
                break;
            case 0xFFB04F:
            case 0xF0C41643:
                // Serial.print(F("IR_KEY_CONTROL"));
                break;
            case 0xFFA857:
            case 0xA3C8EDDB:
                //Serial.print(F("IR_KEY_ENTER"));
                btnEnter();
                break;
            case 0xFF6897:
            case 0xC101E57B:
                //Serial.print(F("ZERO"));
                numericButton = 0;
                break;
            case 0xFF30CF:
            case 0x9716BE3F:
                // Serial.print(F("ONE"));
                numericButton = 1;
                break;
            case 0xFF18E7:
            case 0x3D9AE3F7:
                //Serial.print(F("TWO"));
                numericButton = 2;
                break;
            case 0xFF7A85:
            case 0x6182021B:
                //Serial.print(F("THREE"));
                numericButton = 3;
                break;
            case 0xFF10EF:
            case 0x8C22657B:
                //Serial.print(F("FOUR"));
                numericButton = 4;
                break;
            case 0xFF38C7:
            case 0x488F3CBB:
                //Serial.print(F("FIVE"));
                numericButton = 5;
                break;
            case 0xFF5AA5:
            case 0x449E79F:
                //Serial.print(F("SIX"));
                numericButton = 6;
                break;
            case 0xFF42BD:
            case 0x32C6FDF7:
                //Serial.print(F("SEVEN"));
                numericButton = 7;
                break;
            case 0xFF4AB5:
            case 0x1BC0157B:
                //Serial.print(F("EIGHT"));
                numericButton = 8;
                break;
            case 0xFF52AD:
            case 0x3EC3FC1B:
                //Serial.print(F("NINE"));
                numericButton = 9;
                break;
            default:
                //Serial.print(F("UNKNOWN"));
                break;
        }

        //Serial.print(F(" => hex: "));
        //Serial.print(results.value, HEX);
        //Serial.println();

        irrecv.resume(); // Receive the next value
    } else {
        defaultActions();
    }

    if (numericButton != 10) {
        if (lastNumericButton == 10) {
            lastNumericButton = numericButton;
            lastNumericButtonTime = millis();
        } else if (newNumericButton == 10) {
            newNumericButton = numericButton;
        }
    }

    if (lastNumericButton != 10
            && (millis() - lastNumericButtonTime > timeoutDelay)) {
        if (newNumericButton != 10) {
            selectStation(lastNumericButton * 10 + newNumericButton);
        } else if (lastNumericButton > 0) {
            selectStation(lastNumericButton);
        }
        newNumericButton = 10;
        lastNumericButton = 10;
    }

    delay(10);
}

void selectStation(uint8_t index) {

    if (index == 0) {
        return;
    }

    index--; //numeracja od 0

    if (index < STATION_COUNT) {
        stationIndex = index;
        setStation(index);
    }
}

void setStation(uint8_t index) {
    radio.mute();
    radio.selectFrequency(stations[index]);
    radio.turnTheSoundBackOn();
    saveStation(stations[index]);
}

void btnTest() {
    if (!buttonWasReleased && applicationState != 0) {
        return;
    }
    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN:
            displayDateAndTempInfo();
            setApplicationState(APP_STATE_EXTRA_INFO);
            break;
        case APP_STATE_EXTRA_INFO:
            setApplicationState(APP_STATE_MAIN);
            break;
    }
}

void displayDateAndTempInfo() {
    RTCDateTime dt = clock.getDateTime();
    float temperature = clock.readTemperature();

    display.clearDisplay();
    display.setCursor(0, 0);
    display.setTextColor(BLACK);
    display.setTextSize(2);

    //display time
    display.print(dt.hour);
    display.print(":");
    if (dt.minute < 10) {
        display.print("0");
    }
    display.print(dt.minute);
    display.println();

    //display date
    if (dt.day < 10) {
        display.print("0");
    }
    display.print(dt.day);
    display.print(F("-"));
    if (dt.month < 10) {
        display.print("0");
    }
    display.print(dt.month);
    display.println();

    //display temperature
    display.print(temperature);
    display.println(F(" C"));
    display.display();
}

void btnExit() {
    setApplicationState(APP_STATE_MAIN);
}

/**
 * Set next station
 */
void setNextStation() {
    if (stationIndex < (STATION_COUNT - 1)) {
        stationIndex++;
    } else {
        stationIndex = 0;
    }

    setStation(stationIndex);
}

/**
 * Set previous station
 */
void setPreviousStation() {
    if (stationIndex > 0) {
        stationIndex--;
    } else {
        stationIndex = STATION_COUNT - 1;
    }

    setStation(stationIndex);
}

/**
 * Mute or unmute radio
 */
void mute() {
    if (radio.isMuted()) {
        radio.turnTheSoundBackOn();
        evc_mute(false);
    } else {
        radio.mute();
        evc_mute(true);
    }

    setApplicationState(APP_STATE_MAIN);
}

void openMainMenu() {
    setApplicationState(APP_STATE_MENU);
    selectedMenuItem = MENU_MAIN_SEARCH;
    displayMainMenu();
}

void selectPrevItemInnMainMenu() {
    if (selectedMenuItem > 0)
        selectedMenuItem--;
    displayMainMenu();
}

void selectNextItemInMainMenu() {
    if (selectedMenuItem < (MENU_MAIN_LINES - 1))
        selectedMenuItem++;
    displayMainMenu();
}

void openConfigMenu() {
    setApplicationState(APP_STATE_CONFIG);
    selectedMenuItem = 0;
    displayConfigMenu();
}

void selectNextItemInConfigMenu() {
    if (selectedMenuItem < MENU_CONF_LINES - 1)
        selectedMenuItem++;
    displayConfigMenu();
}

void selectPrevItemInConfigMenu() {
    if (selectedMenuItem > 0)
        selectedMenuItem--;
    displaySearchLevelMenu();
}

void setSearchLevel() {

    searchLevel = selectedMenuItem + 1;

    switch (searchLevel) {
        case LOW_STOP_LEVEL:
            radio.setSearchLowStopLevel();
            saveSearchLevel (LOW_STOP_LEVEL);
            break;
        case MID_STOP_LEVEL:
            radio.setSearchMidStopLevel();
            saveSearchLevel (MID_STOP_LEVEL);
            break;
        case HIGH_STOP_LEVEL:
            radio.setSearchHighStopLevel();
            saveSearchLevel (HIGH_STOP_LEVEL);
            break;
    }

    setApplicationState(APP_STATE_MAIN);
}

void selectNextItemInConfigSearchLevelMenu() {
    if (selectedMenuItem < MENU_SEARCH_LEVEL_LINES - 1)
        selectedMenuItem++;
    displaySearchLevelMenu();
}
void selectPrevItemInConfigSearchLevelMenu() {
    if (selectedMenuItem > 0)
        selectedMenuItem--;
    displaySearchLevelMenu();
}

void openConfigSearchLevelMenu() {
    setApplicationState(APP_STATE_CONFIG_SEARCH_LEVEL);
    selectedMenuItem = searchLevel - 1; //available levels: 1, 2, 3
    displaySearchLevelMenu();
}

void searchNextStation() {
// Search ahead
    byte isBandLimitReached = false;
    radio.setSearchUp();
    isBandLimitReached = radio.searchNextMuting();
    if (isBandLimitReached) {
        radio.setSearchDown();
        isBandLimitReached = radio.searchNextMuting();
    }
    displayDataWithMsg(F("<Search>"));
}

void searchPrevStation() {
    byte isBandLimitReached;
    radio.setSearchDown();
    isBandLimitReached = radio.searchNextMuting();
    if (isBandLimitReached) {
        radio.setSearchUp();
        isBandLimitReached = radio.searchNextMuting();
    }
    displayDataWithMsg(F("<Search>"));
}

void searchStation() {
    setApplicationState(APP_STATE_SEARCH);
    saveDefaultStationsFlag(false);
    displayDataWithMsg(F("<Search>"));
}

void fineSearchNextStation() {
    if (selectedStation < FREQ_MAX) {
        selectedStation += .1;
        radio.selectFrequency(selectedStation);
        displayDataWithMsg(F("<Fine search>"));
        saveStation(selectedStation);
    }
}

void fineSearchPrevStation() {
    if (selectedStation > FREQ_MIN) {
        selectedStation -= .1;
        radio.selectFrequency(selectedStation);
        displayDataWithMsg(F("<Fine search>"));
        saveStation(selectedStation);
    }
}

void fineSearch() {
    setApplicationState(APP_STATE_FINE_SEARCH);
    saveDefaultStationsFlag(false);
    selectedStation = radio.readFrequencyInMHz();
    displayDataWithMsg(F("<Fine search>"));
}

void volumeDown() {
    volume = volume + VOLUME_STEP;
    if (volume >= VOLUME_MUTE_STEP) {
        volume = VOLUME_MUTE_STEP;
        saveVolume(VOLUME_MUTE);
        evc_setVolume(VOLUME_MUTE);
    } else {
        saveVolume((byte) volume);
        evc_setVolume(volume);
    }
}

void volumeUp() {
    if ((volume - VOLUME_STEP) < 0) {
        volume = 0;
    } else {
        volume = volume - VOLUME_STEP;
    }
    saveVolume((byte) volume);
    evc_setVolume(volume);
}

void btnNext() {
    if (!buttonWasReleased)
        return;

    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN:
            setNextStation();
            break;
        case APP_STATE_MENU:
            selectNextItemInMainMenu();
            break;
        case APP_STATE_CONFIG:
            selectNextItemInConfigMenu();
            break;
        case APP_STATE_CONFIG_SEARCH_LEVEL:
            selectNextItemInConfigSearchLevelMenu();
            break;
        case APP_STATE_SEARCH:
            searchNextStation();
            break;
        case APP_STATE_FINE_SEARCH:
            fineSearchNextStation();
            break;
    }
}

void btnPrev() {
    if (!buttonWasReleased)
        return;

    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN:
            setPreviousStation();
            break;
        case APP_STATE_MENU:
            selectPrevItemInnMainMenu();
            break;
        case APP_STATE_SEARCH:
            searchPrevStation();
            break;
        case APP_STATE_FINE_SEARCH:
            fineSearchPrevStation();
            break;
        case APP_STATE_CONFIG:
            selectPrevItemInConfigMenu();
            break;
        case APP_STATE_CONFIG_SEARCH_LEVEL:
            selectPrevItemInConfigSearchLevelMenu();
            break;
    }
}

void btnPlus() {
    if (!buttonWasReleased && applicationState != 0) {
        return;
    }
    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN:
            volumeUp();
            break;
    }
}

void btnMinus() {
    if (!buttonWasReleased && applicationState != 0) {
        return;
    }
    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN:
            volumeDown();
            break;
    }
}

void displayMainMenu() {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.setTextColor(BLACK);
    display.setTextSize(1);

    for (int i = 0; i < MENU_MAIN_LINES; i++) {
        strcpy_P(buffer, (char*) pgm_read_word(&(mainMenu[i])));

        if (i == selectedMenuItem) {
            display.setTextColor(WHITE, BLACK);
            display.println(buffer);
            display.setTextColor(BLACK);
        } else {
            display.println(buffer);
        }
    }

    display.display();
}

void btnMenu() {
    if (!buttonWasReleased) {
        return;
    }

    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN:
            openMainMenu();
            break;
    }
}

void btnEnter() {
    if (!buttonWasReleased) {
        return;
    }

    buttonWasReleased = false;

    switch (applicationState) {
        case APP_STATE_MAIN: {
            mute();
            break;
        }
        case APP_STATE_MENU: {
            switch (selectedMenuItem) {
                case MENU_MAIN_SEARCH:
                    searchStation();
                    break;
                case MENU_MAIN_FINE_SEARCH:
                    fineSearch();
                    break;
                case MENU_MAIN_REGISTER:
                    registerStations();
                    break;
                case MENU_MAIN_CONFIG:
                    openConfigMenu();
                    break;
                case MENU_MAIN_DEFAULTS:
                    restoreDefaultStations();
                    break;
            }
            break;
        }
        case APP_STATE_CONFIG: {
            //Show config menu
            switch (selectedMenuItem) {
                case MENU_CONFIG_SEARCH_LEVEL:
                    openConfigSearchLevelMenu();
                    break;
            }
            break;
        }
        case APP_STATE_CONFIG_SEARCH_LEVEL: {
            setSearchLevel();
            break;
        }
        case APP_STATE_SEARCH:              //Exit from Search
        case APP_STATE_FINE_SEARCH: {       //Exit from Fine Search
            setApplicationState(APP_STATE_MAIN);
            break;
        }
    }
}

// Saves the search level in the EEPROM
void saveSearchLevel(byte searchLevel) {
    mem.write(EEPROM_SEARCH_LEVEL_MARKER,
    EEPROM_SEARCH_LEVEL_MARKER_VALUE);
    delay(10);
    mem.write(EEPROM_SEARCH_LEVEL, searchLevel);
    delay(10);
}

void saveVolume(byte volume) {
    mem.write(EEPROM_VOLUME_MARKER,
    EEPROM_VOLUME_MARKER_VALUE);
    delay(10);
    mem.write(EEPROM_VOLUME, volume);
    delay(10);
}

void saveDefaultStationsFlag(boolean defaultStationsFlagValue) {
    defaultStationsFlag = defaultStationsFlagValue;
    mem.write(EEPROM_DEFAULT_STATIONS_MARKER,
    EEPROM_DEFAULT_STATIONS_MARKER_VALUE);
    delay(10);
    mem.write(EEPROM_DEFAULT_STATIONS, defaultStationsFlag);
    delay(10);
}

void displaySearchLevelMenu() {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.setTextColor(BLACK);
    display.setTextSize(1);

    for (int i = 0; i < MENU_SEARCH_LEVEL_LINES; i++) {
        strcpy_P(buffer, (char*) pgm_read_word(&(searchLevelMenu[i])));
        if (i == selectedMenuItem) {
            display.setTextColor(WHITE, BLACK);
            display.println(buffer);
            display.setTextColor(BLACK);
        } else {
            display.println(buffer);
        }
    }
    display.display();
}

void displayConfigMenu() {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.setTextColor(BLACK);
    display.setTextSize(1);

    for (int i = 0; i < MENU_CONF_LINES; i++) {
        strcpy_P(buffer, (char*) pgm_read_word(&(confMenu[i])));
        if (i == selectedMenuItem) {
            display.setTextColor(WHITE, BLACK);
            display.println(buffer);
            display.setTextColor(BLACK);
        } else {
            display.println(buffer);
        }
    }
    display.display();
}

void setApplicationState(uint8_t state) {
    applicationState = state;
}

void restoreDefaultStations() {
    loadDefaultStations();
    radio.mute();
    radio.selectFrequency(stations[0]);
    radio.turnTheSoundBackOn();
    saveStation(stations[stationIndex]);
    saveDefaultStationsFlag(true);
    setApplicationState(APP_STATE_MAIN);
}

void displaySearchProgress(int progress) {
    display.clearDisplay();
    display.setTextColor(BLACK);
    display.setCursor(0, 0);
    display.setTextSize(1);
    display.println(F("<Searching>"));
    display.println(progress);
    display.display();
}

// Register stations
// Stores all stations found in the array
void registerStations() {
    byte isBandLimitReached = 0;
    byte progress = 0;

    radio.mute();
    radio.selectFrequency(FREQ_MIN);
    radio.setSearchUp();

    while (!isBandLimitReached && (progress < STATION_COUNT)) {
        isBandLimitReached = radio.searchNext();
        stations[progress] = radio.readFrequencyInMHz();
        progress++;
        displaySearchProgress(progress);
    }

    radio.turnTheSoundBackOn();

// Starts station
    stationIndex = 0;
    saveStation(stations[stationIndex]);

    saveDefaultStationsFlag(false);
    setApplicationState(APP_STATE_MAIN);
}

 

pilnikov
pilnikov аватар
Offline
Зарегистрирован: 28.08.2015

слово "contrast" поищите в тексте

/строчка 460 как пример/

samand587
Offline
Зарегистрирован: 21.02.2020

pilnikov пишет:
слово "contrast" ...

Я это слово искал, но видать плохо! Вам спасибо за правильный совет! Осталось разобраться с пультом.

З.Ы. Автор, к сожалению, не отвечает. Плохо!

CyberVad
Offline
Зарегистрирован: 30.07.2018

Товарищи! 
Почти собрал я ё-радио, но вот какая засада: нет автовоспроизведения, включаешь и ничего пока не нажмёшь "Пуск". Как бы это победить?
А так очень даже ничего