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 }