#include "Arduino.h"
#include "Audio.h"
#include "SD.h"
#include "FS.h"
#include "SPI.h"
#include <ArduinoJson.h>
#include <ezButton.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define USE_UTF8_LONG_NAMES 1
#define SDFATFS_USED
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3
#define SDFAT_FILE_TYPE 3
// Digital I/O used
#define SD_CS 5
#define SPI_MOSI 23
#define SPI_MISO 19
#define SPI_SCK 18
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26
#define TRIGGER_SWITCH 4
#define LED_BUILTIN 2
#define SSD1306_NO_SPLASH 1
Audio audio;
ezButton button(TRIGGER_SWITCH);
TaskHandle_t MainTaskHandle;
TaskHandle_t AudioTaskHandle;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
struct Config
{
long delay;
int volume;
int debounceTime;
bool startOnRising;
char file[64];
char readyFile[64];
};
const char *filename = "/config.txt";
Config config;
bool flag = true;
bool lastFlag = true;
void cardInfo()
{
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE)
{
Serial.println(F("No SD card attached"));
return;
}
Serial.print(F("SD Card Type: "));
if (cardType == CARD_MMC)
{
Serial.println(F("MMC"));
}
else if (cardType == CARD_SD)
{
Serial.println(F("SDSC"));
}
else if (cardType == CARD_SDHC)
{
Serial.println(F("SDHC"));
}
else
{
Serial.println(F("UNKNOWN"));
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
}
void loadConfiguration(const char *filename, Config &config)
{
File file = SD.open(filename);
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, file);
if (error)
{
Serial.println(F("Failed to read file, using default configuration"));
}
config.delay = doc["delay"] | 0;
config.volume = doc["volume"] | 21;
config.debounceTime = doc["debounce_time"] | 50;
config.startOnRising = doc["start_on_rising"] | true;
strlcpy(config.file, doc["file"] | "beep.mp3", sizeof(config.file));
strlcpy(config.readyFile, doc["ready_file"] | "beep.mp3", sizeof(config.readyFile));
file.close();
}
void setTrack(String track)
{
audio.stopSong();
audio.connecttoFS(SD, track.c_str());
}
static void AudioTask(void *pvParameters)
{
while (1)
{
Serial.println(F("AudioTask Running"));
vTaskDelay(config.delay / portTICK_PERIOD_MS);
Serial.println(F("Play AudioFile"));
setTrack(config.file);
vTaskDelete(NULL);
}
vTaskDelete(NULL);
}
void start()
{
xTaskCreate(AudioTask, "AudioTask", 10000, NULL, 1, &AudioTaskHandle);
}
void stop()
{
audio.stopSong();
if (AudioTaskHandle != NULL)
{
//vTaskDelete(AudioTaskHandle);
}
}
static void MainTask(void *pvParameters)
{
while (1)
{
audio.loop();
button.loop();
if (button.isPressed())
{
Serial.println(F("TOGGLE HIGH"));
display.fillRect(122, 2, 4, 4, WHITE);
display.display();
if (config.startOnRising != true)
{
start();
}
else
{
stop();
}
}
if (button.isReleased())
{
Serial.println(F("TOGGLE LOW"));
display.fillRect(122, 2, 4, 4, BLACK);
display.display();
if (config.startOnRising != true)
{
stop();
}
else
{
start();
}
}
vTaskDelay(1 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(115200);
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
pinMode(TRIGGER_SWITCH, INPUT_PULLUP);
//pinMode(TRIGGER_SWITCH, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
// SPI.setFrequency(1000000);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.display();
//display.drawPixel(10, 10, WHITE);
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F("Soundcontroller"));
if (!SD.begin(SD_CS))
{
Serial.println(F("Card Mount Failed"));
return;
}
Serial.println(F("Getting CardInfo..."));
cardInfo();
Serial.println(F("Loading configuration..."));
loadConfiguration(filename, config);
button.setDebounceTime(config.debounceTime);
Serial.print(F("delay: "));
Serial.println(config.delay);
Serial.print(F("volume: "));
Serial.println(config.volume);
Serial.print(F("start_on_rising: "));
Serial.println(config.startOnRising);
Serial.print(F("ready_file: "));
Serial.println(config.readyFile);
Serial.print(F("file: "));
Serial.println(config.file);
display.setCursor(0, 20);
display.println(config.delay);
display.setCursor(40, 20);
display.println(config.debounceTime);
display.setCursor(80, 20);
display.println(config.volume);
display.setCursor(120, 20);
display.println(config.startOnRising);
display.setCursor(0, 30);
display.println(config.readyFile);
display.setCursor(0, 40);
display.println(config.file);
display.drawRect(120, 0, 8, 8, WHITE);
display.fillRect(122, 2, 4, 4, WHITE);
display.display();
/*
File file = SD.open(filename, FILE_READ);
if (!file) {
Serial.println("Opening file to read failed");
return;
}
Serial.println("File Content:");
while (file.available()) {
Serial.print((char)file.read());
}
Serial.println();
file.close();
*/
/*
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(1500);
}
*/
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(config.volume); // 0...21
digitalWrite(LED_BUILTIN, HIGH);
// audio.connecttoFS(SD, "320k_test.mp3");
// audio.connecttoFS(SD, "wobble.mp3");
audio.connecttoFS(SD, config.readyFile);
// audio.connecttoFS(SD, "220713_Sirenen_VMCStudios_Final.mp3");
// audio.connecttoFS(SD, "beep.mp3");
// audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u");
// audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx");
// audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.aac"); // 128k aac
// audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/sample1.m4a"); // m4a
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/test_16bit_stereo.wav"); // wav
// audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de");
xTaskCreate(MainTask, "MainTask", 10000, NULL, 1, &MainTaskHandle);
}
void loop()
{
/*
audio.loop();
button.loop();
if (button.isPressed())
{
Serial.println(F("TOGGLE HIGH"));
if (config.startOnRising != true)
{
start();
}
else
{
stop();
}
}
if (button.isReleased())
{
Serial.println(F("TOGGLE LOW"));
if (config.startOnRising != true)
{
stop();
}
else
{
start();
}
}
*/
/*
flag = digitalRead(TRIGGER_SWITCH);
if (lastFlag != flag)
{
lastFlag = flag;
if (lastFlag == HIGH)
{
Serial.println(F("TOGGLE HIGH"));
if (config.startOnRising == true)
{
start();
}
else
{
stop();
}
}
else
{
Serial.println(F("TOGGLE LOW"));
if (config.startOnRising == false)
{
start();
}
else
{
stop();
}
}
}
*/
}
// optional
void audio_info(const char *info)
{
Serial.print("info ");
Serial.println(info);
}
void audio_id3data(const char *info)
{ // id3 metadata
Serial.print("id3data ");
Serial.println(info);
}
void audio_eof_mp3(const char *info)
{ // end of file
Serial.print("eof_mp3 ");
Serial.println(info);
}
void audio_showstation(const char *info)
{
Serial.print("station ");
Serial.println(info);
}
void audio_showstreamtitle(const char *info)
{
Serial.print("streamtitle ");
Serial.println(info);
}
void audio_bitrate(const char *info)
{
Serial.print("bitrate ");
Serial.println(info);
}
void audio_commercial(const char *info)
{ // duration in sec
Serial.print("commercial ");
Serial.println(info);
}
void audio_icyurl(const char *info)
{ // homepage
Serial.print("icyurl ");
Serial.println(info);
}
void audio_lasthost(const char *info)
{ // stream URL played
Serial.print("lasthost ");
Serial.println(info);
}
void audio_eof_speech(const char *info)
{
Serial.print("eof_speech ");
Serial.println(info);
}