acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
Simple_WiFi_Radio_IR.ino (9972B)
1 // this is the same example as Webradio_I2S.ino only with an IR remote control 2 3 #include <Arduino.h> 4 #include <Preferences.h> 5 #include <SPI.h> 6 #include <WiFi.h> 7 #include "tft.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-TFT-Library-ILI9486" 8 #include "Audio.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-audioI2S" 9 #include "IR.h" //see my repository at github "ESP32-IR-Remote-Control" 10 11 12 #define TFT_CS 22 13 #define TFT_DC 21 14 #define TP_CS 16 15 #define TP_IRQ 39 16 #define SPI_MOSI 23 17 #define SPI_MISO 19 18 #define SPI_SCK 18 19 #define I2S_DOUT 25 20 #define I2S_BCLK 27 21 #define I2S_LRC 26 22 #define IR_PIN 34 23 24 Preferences pref; 25 TFT tft; // @suppress("Abstract class cannot be instantiated") 26 TP tp(TP_CS, TP_IRQ); 27 Audio audio; 28 IR ir(IR_PIN); // do not change the objectname, it must be "ir" 29 30 String ssid = "*********"; 31 String password = "*********"; 32 33 String stations[] ={ 34 "0n-80s.radionetz.de:8000/0n-70s.mp3", 35 "mediaserv30.live-streams.nl:8000/stream", 36 "www.surfmusic.de/m3u/100-5-das-hitradio,4529.m3u", 37 "stream.1a-webradio.de/deutsch/mp3-128/vtuner-1a", 38 "mp3.ffh.de/radioffh/hqlivestream.aac", // 128k aac 39 "www.antenne.de/webradio/antenne.m3u", 40 "listen.rusongs.ru/ru-mp3-128", 41 "edge.audio.3qsdn.com/senderkw-mp3", 42 "macslons-irish-pub-radio.com/media.asx", 43 }; 44 45 //some global variables 46 47 uint8_t max_volume = 21; 48 uint8_t max_stations = 0; //will be set later 49 uint8_t cur_station = 0; //current station(nr), will be set later 50 uint8_t cur_volume = 0; //will be set from stored preferences 51 int8_t cur_btn =-1; //current button (, -1 means idle) 52 53 enum action{VOLUME_UP=0, VOLUME_DOWN=1, STATION_UP=2, STATION_DOWN=3}; 54 enum staus {RELEASED=0, PRESSED=1}; 55 56 struct _btns{ 57 uint16_t x; //PosX 58 uint16_t y; //PosY 59 uint16_t w; //Width 60 uint16_t h; //Hight 61 uint8_t a; //Action 62 uint8_t s; //Status 63 }; 64 typedef _btns btns; 65 66 btns btn[4]; 67 68 //************************************************************************************************** 69 // G U I * 70 //************************************************************************************************** 71 void draw_button(btns b){ 72 uint16_t color=TFT_BLACK; 73 uint8_t r=4, o=r*3; 74 if(b.s==RELEASED) color=TFT_GOLD; 75 if(b.s==PRESSED) color=TFT_DEEPSKYBLUE; 76 tft.drawRoundRect(b.x, b.y, b.w, b.h, r, color); 77 switch(b.a){ 78 case VOLUME_UP: 79 tft.fillTriangle(b.x+b.w/2, b.y+o, b.x+o, b.y+b.h-o, b.x+b.w-o, b.y+b.h-o, color); break; 80 case VOLUME_DOWN: 81 tft.fillTriangle(b.x+o, b.y+o, b.x+b.w/2, b.y+b.h-o, b.x+b.w-o, b.y+o, color); break; 82 case STATION_UP: 83 tft.fillTriangle(b.x+o, b.y+o, b.x+o, b.y+b.h-o, b.x+b.w-o, b.y+b.h/2, color); break; 84 case STATION_DOWN: 85 tft.fillTriangle(b.x+b.w-o, b.y+o, b.x+o, b.y+b.h/2, b.x+b.w-o, b.y+b.h-o, color); break; 86 } 87 } 88 void write_stationNr(uint8_t nr){ 89 tft.fillRect(80, 250, 80, 60, TFT_BLACK); 90 String snr = String(nr); 91 if(snr.length()<2) snr = "0"+snr; 92 tft.setCursor(98, 255); 93 tft.setFont(Times_New_Roman66x53); 94 tft.setTextColor(TFT_YELLOW); 95 tft.print(snr); 96 } 97 void write_volume(uint8_t vol){ 98 tft.fillRect(320, 250, 80, 60, TFT_BLACK); 99 String svol = String(vol); 100 if(svol.length()<2) svol = "0"+svol; 101 tft.setCursor(338, 255); 102 tft.setFont(Times_New_Roman66x53); 103 tft.setTextColor(TFT_YELLOW); 104 tft.print(svol); 105 } 106 void write_stationName(String sName){ 107 tft.fillRect(0, 0, 480, 100, TFT_BLACK); 108 tft.setFont(Times_New_Roman43x35); 109 tft.setTextColor(TFT_CORNSILK); 110 tft.setCursor(20, 20); 111 tft.print(sName); 112 } 113 void write_streamTitle(String sTitle){ 114 tft.fillRect(0, 100, 480, 150, TFT_BLACK); 115 tft.setFont(Times_New_Roman43x35); 116 tft.setTextColor(TFT_LIGHTBLUE); 117 tft.setCursor(20, 100); 118 tft.print(sTitle); 119 } 120 void volume_up(){ 121 if(cur_volume < max_volume){ 122 cur_volume++; 123 write_volume(cur_volume); 124 audio.setVolume(cur_volume); 125 pref.putShort("volume", cur_volume);} // store the current volume in nvs 126 } 127 void volume_down(){ 128 if(cur_volume>0){ 129 cur_volume-- ; 130 write_volume(cur_volume); 131 audio.setVolume(cur_volume); 132 pref.putShort("volume", cur_volume);} // store the current volume in nvs 133 } 134 void station_up(){ 135 if(cur_station < max_stations-1){ 136 cur_station++; 137 write_stationNr(cur_station); 138 tft.fillRect(0, 0, 480, 250, TFT_BLACK); 139 audio.connecttohost(stations[cur_station].c_str()); 140 pref.putShort("station", cur_station);} // store the current station in nvs 141 } 142 void station_down(){ 143 if(cur_station > 0){ 144 cur_station--; 145 write_stationNr(cur_station); 146 tft.fillRect(0, 0, 480, 250, TFT_BLACK); 147 audio.connecttohost(stations[cur_station].c_str()); 148 pref.putShort("station", cur_station);} // store the current station in nvs 149 } 150 151 152 //************************************************************************************************** 153 // S E T U P * 154 //************************************************************************************************** 155 void setup() { 156 btn[0].x= 20; btn[0].y=250; btn[0].w=60; btn[0].h=60; btn[0].a=STATION_DOWN; btn[0].s=RELEASED; 157 btn[1].x=160; btn[1].y=250; btn[1].w=60; btn[1].h=60; btn[1].a=STATION_UP; btn[1].s=RELEASED; 158 btn[2].x=260; btn[2].y=250; btn[2].w=60; btn[2].h=60; btn[2].a=VOLUME_UP; btn[2].s=RELEASED; 159 btn[3].x=400; btn[3].y=250; btn[3].w=60; btn[3].h=60; btn[3].a=VOLUME_DOWN; btn[3].s=RELEASED; 160 max_stations= sizeof(stations)/sizeof(stations[0]); log_i("max stations %i", max_stations); 161 Serial.begin(115200); 162 SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 163 pref.begin("WebRadio", false); // instance of preferences for defaults (station, volume ...) 164 if(pref.getShort("volume", 1000) == 1000){ // if that: pref was never been initialized 165 pref.putShort("volume", 10); 166 pref.putShort("station", 0); 167 } 168 else{ // get the stored values 169 cur_station = pref.getShort("station"); 170 cur_volume = pref.getShort("volume"); 171 } 172 WiFi.disconnect(); 173 WiFi.begin(ssid.c_str(), password.c_str()); 174 while (WiFi.status() != WL_CONNECTED) {delay(1500); Serial.print(".");} 175 log_i("Connected to %s", WiFi.SSID().c_str()); 176 tft.begin(TFT_CS, TFT_DC, SPI_MOSI, SPI_MISO, SPI_SCK); 177 tft.setFrequency(20000000); 178 tft.setRotation(3); 179 tp.setRotation(3); 180 tft.setFont(Times_New_Roman43x35); 181 tft.fillScreen(TFT_BLACK); 182 ir.begin(); // Init InfraredDecoder 183 audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); 184 audio.setVolume(cur_volume); // 0...21 185 audio.connecttohost(stations[cur_station].c_str()); 186 for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++) draw_button(btn[i]); 187 write_volume(cur_volume); 188 write_stationNr(cur_station); 189 } 190 //************************************************************************************************** 191 // L O O P * 192 //************************************************************************************************** 193 void loop() 194 { 195 audio.loop(); 196 tp.loop(); 197 ir.loop(); 198 } 199 //************************************************************************************************** 200 // E V E N T S * 201 //************************************************************************************************** 202 void audio_info(const char *info){ 203 Serial.print("audio_info: "); Serial.println(info); 204 } 205 void audio_showstation(const char *info){ 206 write_stationName(String(info)); 207 } 208 void audio_showstreamtitle(const char *info){ 209 String sinfo=String(info); 210 sinfo.replace("|", "\n"); 211 write_streamTitle(sinfo); 212 } 213 214 void tp_pressed(uint16_t x, uint16_t y){ 215 for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++){ 216 if(x>btn[i].x && (x<btn[i].x+btn[i].w)){ 217 if(y>btn[i].y && (y<btn[i].y+btn[i].h)){ 218 cur_btn=i; 219 btn[cur_btn].s=PRESSED; 220 draw_button(btn[cur_btn]); 221 } 222 } 223 } 224 } 225 void tp_released(){ 226 if(cur_btn !=-1){ 227 btn[cur_btn].s=RELEASED; 228 draw_button(btn[cur_btn]); 229 switch(btn[cur_btn].a){ 230 case VOLUME_UP: volume_up(); break; 231 case VOLUME_DOWN: volume_down(); break; 232 case STATION_UP: station_up(); break; 233 case STATION_DOWN: station_down(); break; 234 } 235 } 236 cur_btn=-1; 237 } 238 // Events from IR Library 239 void ir_res(uint32_t res){ 240 if(res < max_stations){ 241 cur_station = res; 242 write_stationNr(cur_station); 243 tft.fillRect(0, 0, 480, 250, TFT_BLACK); 244 audio.connecttohost(stations[cur_station].c_str()); 245 pref.putShort("station", cur_station);} // store the current station in nvs 246 else{ 247 tft.fillRect(0, 0, 480, 250, TFT_BLACK); 248 audio.connecttohost(stations[cur_station].c_str()); 249 } 250 } 251 void ir_number(const char* num){ 252 tft.fillRect(0, 0, 480, 250, TFT_BLACK); 253 tft.setTextSize(7); 254 tft.setTextColor(TFT_CORNSILK); 255 tft.setCursor(50, 70); 256 tft.print(num); 257 } 258 void ir_key(const char* key){ 259 switch(key[0]){ 260 case 'k': break; // OK 261 case 'r': volume_up(); break; // right 262 case 'l': volume_down(); break; // left 263 case 'u': station_up(); break; // up 264 case 'd': station_down(); break; // down 265 case '#': break; // # 266 case '*': break; // * 267 default: break; 268 } 269 }