#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h" // https://github.com/schreibfaul1/ESP32-audioI2S.git
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <ESP32Encoder.h> // https://github.com/madhephaestus/ESP32Encoder.git
#include <EEPROM.h>
#define I2S_DOUT 25 // DIN connection
#define I2S_BCLK 27 // Bit clock
#define I2S_LRC 26 // Left Right Clock
#define CLK 19 // CLK ENCODER
#define DT 18 // DT ENCODER
#define SW 5 // SW ENCODER
#define CH_UP 13 // CH_UP BUTTON
#define CH_DOWN 12 // CH_DOWN BUTTON
#define CH 26 // кол-во станций
Audio audio;
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
ESP32Encoder encoder;
String ssid = "dlink"; // ssid сети WI-FI
String password = "123asdzxc"; // пароль от сети WI-FI
String ch = "connection ";
String bitr;
unsigned long oldPosition = -999,newPosition,times1,times_ch;
bool w=1,w1,ball_1,bass_1,mid_1,treb_1,vol_1;
int ct,old_ct = 1,menu,ball,bass,mid,treb,vol=15;
bool e_vol,e_ball,e_bass,e_mid,e_treb,e_ct;
int i_ch,t_ch,tic_ch;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
const char *listch[]{
"https://rusradio.hostingradio.ru/rusradio96.aacp",
"https://str.pcradio.ru/funradio_sk_80s90s-hi",
"http://radiomv.hostingradio.ru/radiomv256.mp3",
"http://online.sputnik107.ru:8000/sputnik107",
"http://stream1.radiord.ru:8000/live128.mp3",
"http://online-1.gkvr.ru:8000/europa_eka_64.aac",
"http://online-1.gkvr.ru:8000/record_eka_64.aac",
"http://online-1.gkvr.ru:8000/chanson_eka_64.aac",
"http://online.gkvr.ru/radiola_eka_64.aac",
"http://online-1.gkvr.ru:8000/retro_eka_64.aac",
"http://online-1.gkvr.ru:8000/hitfm_eka_64.aac",
"http://online-1.gkvr.ru:8000/dacha_eka_64.aac",
"https://c28.radioboss.fm:18441/eural",
"http://pub0302.101.ru:8000/stream/air/aac/64/101",
"http://radio.dline-media.com/ppr128.mp3",
"http://online.radioc.ru:8000/radioc",
"http://radio.volnafm.ru:8000/ekb",
"http://icecast-vgtrk.cdnvideo.ru/ural_radio_vesti",
"http://icecast-vgtrk.cdnvideo.ru/ural_radio_mayak",
"http://icecast-vgtrk.cdnvideo.ru/ural_radio_rossii",
"http://online-1.gkvr.ru:8000/s2.aac",
"http://online-1.gkvr.ru:8000/bfm_eka_64.aac",
"http://online-1.gkvr.ru:8000/mc_eka_64.aac",
"http://icecast-piterfm.cdnvideo.ru:8000/piterfm",
"http://icecast-radiofortwo.cdnvideo.ru:8000/radiofortwo",
"http://streams.radiosarova.ru/r13radio",
};
void setup() {
ESP32Encoder::useInternalWeakPullResistors=UP;
encoder.attachHalfQuad(DT, CLK);
encoder.setCount(0);
Serial.begin(9600);
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
lcd.init();lcd.backlight();
lcd.setCursor(0,0);lcd.print(" ESP32 RADIO ");
lcd.setCursor(0,1);lcd.print(" PCM5102A ");
delay(2000);
while (WiFi.status() != WL_CONNECTED) delay(100);
lcd.clear();
lcd.setCursor(0,0);lcd.print("IP:");lcd.print(WiFi.localIP());
delay(2000);
lcd.clear();
EEPROM.begin(10);
vol = EEPROM.read(0);
ball = EEPROM.read(1)-16;
bass = EEPROM.read(2)-40;
mid = EEPROM.read(3)-40;
treb = EEPROM.read(4)-40;
ct = EEPROM.read(5);
if(vol>21){vol=0;}
if(ball>16){ball=0;}
if(bass>16){bass=0;}
if(mid>16){mid=0;}
if(treb>16){treb=0;}
if(ct>CH-1){ct=0;}
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
delay(2000);
audio.setBalance(ball);//+-16
audio.setVolume(vol); // 0...21
audio.setTone(0,0,0);//-40+16
pinMode(CH_UP, INPUT_PULLUP);
pinMode(CH_DOWN, INPUT_PULLUP);
pinMode(SW,INPUT); // ENCODER SW
}
void loop(){
newPosition = encoder.getCount()/2;
//// ENCODER VOLUME //////////////////////////////////////////////
if(menu==0){
if(newPosition != oldPosition){oldPosition = newPosition;vol=vol-newPosition;encoder.setCount(0);
newPosition=0;times1=millis();w1=1;if(vol>21){vol=21;}if(vol<0){vol=0;}audio.setVolume(vol);vol_1=1;e_vol=1;}
if(vol_1==1){vol_1=0;lcd.setCursor(9,1);lcd.print("VOL ");lcd.print(vol);lcd.print(" ");}}
///// ENCODER BALANCE ////////////////////////////////////////////
if(menu==1){
if(newPosition != oldPosition){oldPosition = newPosition;ball=ball-newPosition;encoder.setCount(0);
newPosition=0;times1=millis();w1=1;if(ball>16){ball=16;}if(ball<-16){ball=-16;}audio.setBalance(ball);ball_1=1;e_ball=1;}
if(ball_1==1){ball_1=0;lcd.setCursor(0,0);lcd.print("BALANCE ");lcd.print(ball);lcd.print(" dB ");}}
///// ENCODER BASS ////////////////////////////////////////////
if(menu==2){
if(newPosition != oldPosition){oldPosition = newPosition;bass=bass-newPosition;encoder.setCount(0);
newPosition=0;times1=millis();w1=1;if(bass>16){bass=16;}if(bass<-40){bass=-40;}audio.setTone(bass,mid,treb);bass_1=1;e_bass=1;}
if(bass_1==1){bass_1=0;lcd.setCursor(0,0);lcd.print("BASS ");lcd.print(bass);lcd.print(" dB ");}}
///// ENCODER MIDDLE ////////////////////////////////////////////
if(menu==3){
if(newPosition != oldPosition){oldPosition = newPosition;mid=mid-newPosition;encoder.setCount(0);
newPosition=0;times1=millis();w1=1;if(mid>16){mid=16;}if(mid<-40){mid=-40;}audio.setTone(bass,mid,treb);mid_1=1;e_mid=1;}
if(mid_1==1){mid_1=0;lcd.setCursor(0,0);lcd.print("MIDDLE ");lcd.print(mid);lcd.print(" dB ");}}
///// ENCODER TREBLE ////////////////////////////////////////////
if(menu==4){
if(newPosition != oldPosition){oldPosition = newPosition;treb=treb-newPosition;encoder.setCount(0);
newPosition=0;times1=millis();w1=1;if(treb>16){treb=16;}if(treb<-40){treb=-40;}audio.setTone(bass,mid,treb);treb_1=1;e_treb=1;}
if(treb_1==1){treb_1=0;lcd.setCursor(0,0);lcd.print("TREBLE ");lcd.print(treb);lcd.print(" dB ");}}
//// BUTTON //////////////////////////////////////////////
if (digitalRead(13)==LOW){ct++;if(ct>CH-1){ct=0;}w=1;times1=millis();w1=1;ch="connection ";lcd.setCursor(0,0);lcd.print(ch);menu=0;e_ct=1;delay(300);}
if (digitalRead(12)==LOW){ct--;if(ct<0){ct=CH-1;}w=1;times1=millis();w1=1;ch="connection ";lcd.setCursor(0,0);lcd.print(ch);menu=0;e_ct=1;Serial.println(ct);delay(300);}
if (digitalRead(5)==LOW){menu++;if(menu>4){menu=0;}times1=millis();w1=1;lcd.clear();vol_1=1;ball_1=1;bass_1=1;mid_1=1;treb_1=1;if(menu==0){w=1;}delay(300);}
//////////////////////////////////////////////////////////
if (ct != old_ct) {ch!="connection ";audio.connecttohost(listch[ct]);Serial.println(ct);old_ct = ct;w=1;}
if(menu==0){
if(w==1&&ch!="connection "){
lcd.clear();w=0;
lcd.setCursor(0,1);lcd.print("CH");lcd.print(ct);lcd.print(" ");
lcd.print(float(bitr.toInt()/1000),0);lcd.print("k ");
lcd.setCursor(9,1);lcd.print("VOL ");lcd.print(vol);lcd.print(" ");
}
if(millis()-times_ch>500){
times_ch=millis();
int n_ch = ch.length();
String s1 = ch.substring(i_ch,n_ch);
lcd.setCursor(0,0);lcd.print(s1);lcd.print(" ");
tic_ch++;if(tic_ch>n_ch+4){tic_ch=0;}
if(tic_ch>3&&n_ch>16){i_ch++;}if(i_ch>n_ch){i_ch=0;}
}}
audio.loop();
//// EEPROM ///////////////////////////////////
if(millis()-times1>5000&&w1==1){
if(e_vol==1){e_vol=0;EEPROM.write(0,vol);}
if(e_ball==1){e_ball=0;EEPROM.write(1,ball+16);}
if(e_bass==1){e_bass=0;EEPROM.write(2,bass+40);}
if(e_mid==1){e_mid=0;EEPROM.write(3,mid+40);}
if(e_treb==1){e_treb=0;EEPROM.write(4,treb+40);}
if(e_ct==1){e_ct=0;EEPROM.write(5,ct);}
EEPROM.commit();}
if(millis()-times1>10000&&w1==1){
w1=0;if(menu!=0){w=1;menu=0;}}
} // loop
void audio_showstation(const char *info) {Serial.print("station "); ch=info; Serial.println(info);}
void audio_showstreamtitle(const char *info) {Serial.print("streamtitle "); Serial.println(info);}
void audio_bitrate(const char *info) {Serial.print("bitrate ");bitr = info; Serial.println(info);}
void audio_icyurl(const char *info) {Serial.print("icyurl "); Serial.println(info);}
void audio_lasthost(const char *info) {Serial.print("lasthost "); Serial.println(info);}