boKontTestESP_4.ino


/*B&O kompatibel WIFI radio.
Hovedparten af nedenstående basere sig på: ESP8266: How To Make Wi-Fi Radio se:
https://www.hackster.io/RoboticaDIY/esp8266-how-to-make-wi-fi-radio-5bee14
Og anvender følgende bibliotek: https://github.com/earlephilhower/ESP8266Audio
tilhørende Earle F. Philhower, III, venligst respekter hans licens.
Bemærk: denne version fungere ikke på ESP8266, men er testet på ESP32 wroom og wrover.
*/

#include <Arduino.h>
#include <WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"

#ifndef STASSID
#define STASSID "netværksnavn"
#define STAPSK  "netværksnøgle"
#endif

const char* ssid = STASSID;
const char* password = STAPSK;
int res = 0;
int i = 0;
int flag = 0;
int p_count = 1;
int playNr = 1;
int count = 0;
const byte in = 33;
const byte interruptPin = 33;
volatile bool readInput = false;
volatile bool startFlag = true;
volatile unsigned long startMillis;
volatile unsigned long endMillis;
volatile unsigned long diffMillis;
volatile unsigned long currentMillis;

void StartStream(int playNr);

char URL[70] = {""};
char URL1[70] = {"http://live-icy.gslb01.dr.dk:8000/A/A03H.mp3"};
char URL2[70] = {"http://live-icy.gslb01.dr.dk:80/A/A04H.mp3"};
char URL3[70] = {"http://live-icy.gslb01.dr.dk:80/A/A05H.mp3"};
char URL4[70] = {"http://live-icy.gslb01.dr.dk:80/A/A08H.mp3"};
char URL5[70] = {"http://live-icy.gslb01.dr.dk:80/A/A25H.mp3"};
char URL6[70] = {"http://live-icy.gslb01.dr.dk:80/A/A29H.mp3"};
char URL7[70] = {"http://live-icy.gslb01.dr.dk:80/A/A22H.mp3"};
char URL8[70] = {"http://live-bauerdk.sharp-stream.com/nova128.mp3"};
char URL9[70] = {"http://live-bauerdk.sharp-stream.com/myrock.mp3"};

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2S *out;

int decode (int res)
  {
    //Serial.println(playNr);
        flag = 1;
        if (res > 0 && res < 10)
          p_count = res;
        switch (res)
        {
        case 20 : {//PHONO
                  p_count = 1;
                  }
                  break;
        case 22 : {//TAPE fr_sl
                  p_count = 1;
                  }
                  break;
        case 3 :  {//NUM
                  //delay (130);
                  //flag = 0;
                  }
                  break;
        case 54 : {//AUX
                  p_count = 1;
                  }
                  break;
        case 38 : {//STOP
                  mp3->stop();
                  flag = 0;
                  }
                  break;
        case 74 : {//T STOP
                  mp3->stop();
                  flag = 0;
                  }
                  break;
        case 37 : {//OFF
                  mp3->stop();
                  flag = 0;
                  }
                  break;
        case 10 : p_count ++;//RIGHT ARROW
                  break;
        case 21 : p_count ++;//RIGHT ARROW
                  break;          
        case 12 : p_count ++;//T RIGHT ARROW
                  break;
        case 57 : p_count --;//LEFT ARROW
                  break;
        case 56 : p_count --;//T LEFT ARROW
                  break;
        case 41 : p_count = 7;//>> RIGHT ARROW
                  break;
        case 40 : p_count = 5;//<< LEFT ARROW
                  break;          
        default:  {
                  flag = 0;
                  return 0;
                  }
                }
                if (flag == 1)
                  {
                if (p_count > 9)
                  {
                  p_count = 1;
                  }
                if (p_count < 1)
                  {
                  p_count = 9;
                  }
                playNr = p_count;
                //Serial.println(playNr);
                StartStream(playNr);
                }
    return 0;
}

void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
{
  const char *ptr = reinterpret_cast<const char *>(cbData);
  (void) isUnicode; // Punt this ball for now
  // Note that the type and string may be in PROGMEM, so copy them to RAM for printf
  char s1[32], s2[64];
  strncpy_P(s1, type, sizeof(s1));
  s1[sizeof(s1)-1]=0;
  strncpy_P(s2, string, sizeof(s2));
  s2[sizeof(s2)-1]=0;
  Serial.printf("METADATA(%s) '%s' = '%s'\n", ptr, s1, s2);
  Serial.flush();
}

void StatusCallback(void *cbData, int code, const char *string)
{
  const char *ptr = reinterpret_cast<const char *>(cbData);
  // Note that the string may be in PROGMEM, so copy it to RAM for printf
  char s1[64];
  strncpy_P(s1, string, sizeof(s1));
  s1[sizeof(s1)-1]=0;
  Serial.printf("STATUS(%s) '%d' = '%s'\n", ptr, code, s1);
  Serial.flush();
}

void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("Connecting");
pinMode(in, INPUT);
pinMode(interruptPin, INPUT);
startMillis = millis();
attachInterrupt(digitalPinToInterrupt(interruptPin), inPut, FALLING);
Serial.println("Connecting to WiFi");

  WiFi.disconnect();
  WiFi.softAPdisconnect(true);
  WiFi.mode(WIFI_STA);
 
  WiFi.begin(ssid, password);

  // Try forever
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("...Connecting to WiFi");
    delay(1000);
  }
  Serial.println("Connected");
  StartStream(playNr);
  audioLogger = &Serial;
}

void StartStream(int playNr)
{
  //Serial.println(playNr);
  if (mp3) {
    mp3->stop();
    delete mp3;
    mp3 = NULL;
  }
  if (out) {
    out->stop();
    delete out;
    out = NULL;
  }
  if (buff) {
    buff->close();
    delete buff;
    buff = NULL;
  }
  if (file) {
    file->close();
    delete file;
    file = NULL;
  }
switch (playNr)
  {  
  case 1 : {
    strcpy(URL, URL1);
  }break;
  case 2 : {
    strcpy(URL, URL2);
  }break;
  case 3 : {
    strcpy(URL, URL3);
  }break;
  case 4 : {
    strcpy(URL, URL4);
  }break;
  case 5 : {
    strcpy(URL, URL5);
  }break;
  case 6 : {
    strcpy(URL, URL6);
  }break;
  case 7 : {
    strcpy(URL, URL7);
  }break;
  case 8 : {
    strcpy(URL, URL8);
  }break;
  case 9 : {
    strcpy(URL, URL9);
  }break;
  default:  {}
  }
  //
  file = new AudioFileSourceICYStream(URL);
  file->RegisterMetadataCB(MDCallback, (void*)"ICY");
  buff = new AudioFileSourceBuffer(file, 65536);
  buff->RegisterStatusCB(StatusCallback, (void*)"buffer");
  out = new AudioOutputI2S();
  mp3 = new AudioGeneratorMP3();
  mp3->RegisterStatusCB(StatusCallback, (void*)"mp3");
  mp3->begin(buff, out);
}



void inPut()
{
   readInput = true;
}

void readInputPin()
  {
   endMillis = millis();
    diffMillis = endMillis - startMillis;
    startMillis = millis();
    if (diffMillis > 60)
    {
      detachInterrupt (digitalPinToInterrupt(interruptPin));
      res = 0;
      delayMicroseconds (200);
        for (i = 1; i < 7; i++)
          {
            delayMicroseconds (3100);
            res = (res << 1) + (!digitalRead (in));
          }
              decode(res);
              Serial.println(res);
              attachInterrupt(digitalPinToInterrupt(interruptPin), inPut, FALLING);
              startFlag = true;
          }      
  }

void loop() {
  // put your main code here, to run repeatedly:
  if (readInput)
  {
    readInput = false;
    //mp3->stop();
    startFlag = false;
    readInputPin();
  }
{
static int lastms = 0;
if (mp3->isRunning()) {
if (millis()-lastms > 1000) {
lastms = millis();
Serial.printf("Running for %d ms...\n", lastms);
Serial.flush();
}
if (!mp3->loop()) mp3->stop();
} else {
Serial.printf("MP3 done\n");
delay(3);
}
}
}

Bemærk: dette er ekspermentel software der er ingen garanti for brugbarhed, det kan derimod sandsynligvis være skadeligt, kun til brug i Danmark.