/*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.