This commit is contained in:
2025-06-18 09:21:10 +08:00
commit b2b79996d7
478 changed files with 82728 additions and 0 deletions

View File

@ -0,0 +1,156 @@
// found this sketch on https://www.mikrocontroller.net/topic/474383
// thanks to Michael U. (amiga)
#include "Arduino.h"
#include "WiFi.h"
#include "SPI.h"
#include "SD.h"
#include "FS.h"
#include "Wire.h"
#include "AC101.h" //https://github.com/schreibfaul1/AC101
// #include "ES8388.h" // https://github.com/maditnerd/es8388
#include "Audio.h" //https://github.com/schreibfaul1/ESP32-audioI2S
// SPI GPIOs
#define SD_CS 13
#define SPI_MOSI 15
#define SPI_MISO 2
#define SPI_SCK 14
// I2S GPIOs, the names refer on AC101, AS1 Audio Kit V2.2 2379
#define I2S_DSIN 25
#define I2S_BCLK 27
#define I2S_LRC 26
#define I2S_MCLK 0
#define I2S_DOUT 35
// I2S GPIOs, the names refer on ES8388, AS1 Audio Kit V2.2 3378
//#define I2S_DSIN 35
//#define I2S_BCLK 27
//#define I2S_LRC 25
//#define I2S_MCLK 0
//#define I2S_DOUT 26
// I2C GPIOs
#define IIC_CLK 32
#define IIC_DATA 33
// buttons
// #define BUTTON_2_PIN 13 // shared mit SPI_CS
#define BUTTON_3_PIN 19
#define BUTTON_4_PIN 23
#define BUTTON_5_PIN 18 // Stop
#define BUTTON_6_PIN 5 // Play
// amplifier enable
#define GPIO_PA_EN 21
//Switch S1: 1-OFF, 2-ON, 3-ON, 4-OFF, 5-OFF
String ssid = "xxxxxxxxx";
String password = "xxxxxxxxx";
static AC101 dac; // AC101
// ES8388 dac; // ES8388 (new board)
int volume = 40; // 0...100
Audio audio;
//#####################################################################
void setup()
{
Serial.begin(115200);
Serial.println("\r\nReset");
Serial.printf_P(PSTR("Free mem=%d\n"), ESP.getFreeHeap());
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
SPI.setFrequency(1000000);
SD.begin(SD_CS);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(100);
}
Serial.printf_P(PSTR("Connected\r\nRSSI: "));
Serial.print(WiFi.RSSI());
Serial.print(" IP: ");
Serial.println(WiFi.localIP());
Serial.printf("Connect to DAC codec... ");
while (not dac.begin(IIC_DATA, IIC_CLK))
{
Serial.printf("Failed!\n");
delay(1000);
}
Serial.printf("OK\n");
dac.SetVolumeSpeaker(volume);
dac.SetVolumeHeadphone(volume);
// ac.DumpRegisters();
// Enable amplifier
pinMode(GPIO_PA_EN, OUTPUT);
digitalWrite(GPIO_PA_EN, HIGH);
// set I2S_MasterClock
audio.i2s_mclk_pin_select(I2S_MCLK);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DSIN);
audio.setVolume(10); // 0...21
audio.connecttoFS(SD, "/320k_test.mp3");
// audio.connecttoSD("/Banana Boat Song - Harry Belafonte.mp3");
// audio.connecttohost("http://mp3channels.webradio.antenne.de:80/oldies-but-goldies");
// audio.connecttohost("http://dg-rbb-http-dus-dtag-cdn.cast.addradio.de/rbb/antennebrandenburg/live/mp3/128/stream.mp3");
// audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de");
}
//-----------------------------------------------------------------------
void loop()
{
audio.loop();
}
// 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);
}

View File

@ -0,0 +1,137 @@
// the pin assignment matches the Olimex ADF board
#include "Arduino.h"
#include "WiFi.h"
#include "SPI.h"
#include "SD.h"
#include "FS.h"
#include "Wire.h"
#include "ES8388.h" // https://github.com/maditnerd/es8388
#include "Audio.h" // https://github.com/schreibfaul1/ESP32-audioI2S
#define SD_CS 21
// GPIOs for SPI
#define SPI_MOSI 13
#define SPI_MISO 12
#define SPI_SCK 14
// I2S GPIOs
#define I2S_SDOUT 26
#define I2S_BCLK 5
#define I2S_LRCK 25
#define I2S_MCLK 0
// I2C GPIOs
#define IIC_CLK 23
#define IIC_DATA 18
// Amplifier enable
#define GPIO_PA_EN 19
char ssid[] = "xxxxxxxxx";
char password[] = "xxxxxxxxx";
int volume = 80; // 0...100
ES8388 es;
Audio audio;
//----------------------------------------------------------------------------------------------------------------------
void setup()
{
Serial.begin(115200);
Serial.println("\r\nReset");
Serial.printf_P(PSTR("Free mem=%d\n"), ESP.getFreeHeap());
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
SPI.setFrequency(1000000);
SD.begin(SD_CS);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.printf_P(PSTR("Connected\r\nRSSI: "));
Serial.print(WiFi.RSSI());
Serial.print(" IP: ");
Serial.println(WiFi.localIP());
Serial.printf("Connect to ES8388 codec... ");
while (not es.begin(IIC_DATA, IIC_CLK))
{
Serial.printf("Failed!\n");
delay(1000);
}
Serial.printf("OK\n");
es.volume(ES8388::ES_MAIN, volume);
es.volume(ES8388::ES_OUT1, volume);
es.volume(ES8388::ES_OUT2, volume);
es.mute(ES8388::ES_OUT1, false);
es.mute(ES8388::ES_OUT2, false);
es.mute(ES8388::ES_MAIN, false);
// Enable amplifier
pinMode(GPIO_PA_EN, OUTPUT);
digitalWrite(GPIO_PA_EN, HIGH);
audio.setPinout(I2S_BCLK, I2S_LRCK, I2S_SDOUT);
audio.i2s_mclk_pin_select(I2S_MCLK);
audio.setVolume(21); // 0...21
audio.connecttohost("http://mp3channels.webradio.antenne.de:80/oldies-but-goldies");
// audio.connecttoFS(SD, "320k_test.mp3");
// audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de");
}
//----------------------------------------------------------------------------------------------------------------------
void loop()
{
audio.loop();
}
//----------------------------------------------------------------------------------------------------------------------
// 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_showstreaminfo(const char *info){
Serial.print("streaminfo ");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);
}

View File

@ -0,0 +1,100 @@
//**********************************************************************************************************
//* audioI2S-- I2S audiodecoder for ESP32, *
//**********************************************************************************************************
//
// first release on 11/2018
// Version 3 , Jul.02/2020
//
//
// THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT.
// FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR
// OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
//
#include "Arduino.h"
#include "WiFiMulti.h"
#include "Audio.h"
#include "SPI.h"
#include "SD.h"
#include "FS.h"
// 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
Audio audio;
WiFiMulti wifiMulti;
String ssid = "xxxxx";
String password = "xxxxx";
void setup() {
pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
SPI.setFrequency(1000000);
Serial.begin(115200);
SD.begin(SD_CS);
WiFi.mode(WIFI_STA);
wifiMulti.addAP(ssid.c_str(), password.c_str());
wifiMulti.run();
if(WiFi.status() != WL_CONNECTED){
WiFi.disconnect(true);
wifiMulti.run();
}
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(12); // 0...21
// audio.connecttoFS(SD, "/320k_test.mp3");
// audio.connecttoFS(SD, "test.wav");
// 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
}
void loop()
{
audio.loop();
if(Serial.available()){ // put streamURL in serial monitor
audio.stopSong();
String r=Serial.readString(); r.trim();
if(r.length()>5) audio.connecttohost(r.c_str());
log_i("free heap=%i", ESP.getFreeHeap());
}
}
// 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);
}

View File

@ -0,0 +1,103 @@
//**********************************************************************************************************
//* audioI2S-- I2S audiodecoder for M5Stack Core2 *
//**********************************************************************************************************
//
// first release on May.12/2021
//
//
// THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT.
// FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR
// OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
//
#include <M5Core2.h>
#include "Audio.h"
// Digital I/O used
#define SD_CS 4
#define SD_MOSI 23
#define SD_MISO 38
#define SD_SCK 18
#define I2S_DOUT 2
#define I2S_BCLK 12
#define I2S_LRC 0
Audio audio;
String ssid = "xxxxxx";
String password = "xxxxxx";
void setup() {
M5.begin(true, true, true, true);
M5.Axp.SetSpkEnable(true);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(2);
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin(SD_SCK, SD_MISO, SD_MOSI);
SPI.setFrequency(1000000);
SD.begin(SD_CS);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(15); // 0...21
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
while (!WiFi.isConnected()) {
delay(10);
}
ESP_LOGI(TAG, "Connected");
ESP_LOGI(TAG, "Starting MP3...\n");
// audio.connecttoFS(SD, "/320k_test.mp3");
// audio.connecttoFS(SD, "test.wav");
audio.connecttohost("http://air.ofr.fm:8008/jazz/mp3/128");
// audio.connecttospeech("Миска вареників з картоплею та шкварками, змащених салом!", "uk-UA");
}
void loop() {
audio.loop();
if(Serial.available()){ // put streamURL in serial monitor
audio.stopSong();
String r=Serial.readString();
r.trim();
if(r.length()>5) audio.connecttohost(r.c_str());
log_i("free heap=%i", ESP.getFreeHeap());
}
}
// 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);
}

View File

@ -0,0 +1,53 @@
// M5Stack Node support
// thanks to Cellie - issue #35 25.Apr.2020
// M5Stack board with Node base also need a MCLK signal on GPIO0.
#include <wm8978.h> /* https://github.com/CelliesProjects/wm8978-esp32 */
#include <Audio.h> /* https://github.com/schreibfaul1/ESP32-audioI2S */
/* M5Stack Node WM8978 I2C pins */
#define I2C_SDA 21
#define I2C_SCL 22
/* M5Stack Node I2S pins */
#define I2S_BCK 5
#define I2S_WS 13
#define I2S_DOUT 2
#define I2S_DIN 34
/* M5Stack WM8978 MCLK gpio number */
#define I2S_MCLKPIN 0
WM8978 dac;
Audio audio;
void setup() {
/* Setup wm8978 I2C interface */
if (!dac.begin(I2C_SDA, I2C_SCL)) {
ESP_LOGE(TAG, "Error setting up dac. System halted");
while (1) delay(100);
}
/* Setup wm8978 I2S interface */
audio.setPinout(I2S_BCK, I2S_WS, I2S_DOUT, I2S_DIN);
/* Setup wm8978 MCLK - for example M5Stack Node needs MCLK on GPIO 0 */
audio.i2s_mclk_pin_select(I2S_MCLKPIN);
WiFi.begin("xxx", "xxx");
while (!WiFi.isConnected()) {
delay(10);
}
ESP_LOGI(TAG, "Connected");
ESP_LOGI(TAG, "Starting MP3...\n");
audio.connecttohost("http://icecast.omroep.nl/3fm-bb-mp3");
dac.setSPKvol(40); /* max 63 */
dac.setHPvol(32, 32);
}
void loop() {
audio.loop();
}

View File

@ -0,0 +1,88 @@
//**********************************************************************************************************
//* audioI2S-- I2S audiodecoder for M5StickC Plus and SPK HAT *
//**********************************************************************************************************
//
// first release on May.12/2021
//
//
// THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT.
// FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR
// OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
//
#include <M5StickCPlus.h>
#include "Audio.h"
Audio audio = Audio(true);
String ssid = "xxxxxxxx";
String password = "xxxxxxxx";
void setup() {
M5.begin(false); //Lcd disabled to reduce noise
M5.Axp.ScreenBreath(1); //Lower Lcd backlight
pinMode(36, INPUT);
gpio_pulldown_dis(GPIO_NUM_25);
gpio_pullup_dis(GPIO_NUM_25);
M5.Beep.tone(44100); //Built-in buzzer tone
M5.Beep.end(); //disabled
audio.setVolume(15); // 0...21
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
while (!WiFi.isConnected()) {
delay(10);
}
ESP_LOGI(TAG, "Connected");
ESP_LOGI(TAG, "Starting MP3...\n");
audio.connecttohost("http://air.ofr.fm:8008/jazz/mp3/128");
// audio.connecttospeech("Миска вареників з картоплею та шкварками, змащених салом!", "uk-UA");
}
void loop() {
audio.loop();
if(Serial.available()){ // put streamURL in serial monitor
audio.stopSong();
String r=Serial.readString();
r.trim();
if(r.length()>5) audio.connecttohost(r.c_str());
log_i("free heap=%i", ESP.getFreeHeap());
}
}
// 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);
}

View File

@ -0,0 +1,158 @@
#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"
// Digital I/O used
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26
Audio audio;
String ssid = "******";
String password = "******";
//****************************************************************************************
// A U D I O _ T A S K *
//****************************************************************************************
struct audioMessage{
uint8_t cmd;
const char* txt;
uint32_t value;
uint32_t ret;
} audioTxMessage, audioRxMessage;
enum : uint8_t { SET_VOLUME, GET_VOLUME, CONNECTTOHOST, CONNECTTOSD };
QueueHandle_t audioSetQueue = NULL;
QueueHandle_t audioGetQueue = NULL;
void CreateQueues(){
audioSetQueue = xQueueCreate(10, sizeof(struct audioMessage));
audioGetQueue = xQueueCreate(10, sizeof(struct audioMessage));
}
void audioTask(void *parameter) {
CreateQueues();
if(!audioSetQueue || !audioGetQueue){
log_e("queues are not initialized");
while(true){;} // endless loop
}
struct audioMessage audioRxTaskMessage;
struct audioMessage audioTxTaskMessage;
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(15); // 0...21
while(true){
if(xQueueReceive(audioSetQueue, &audioRxTaskMessage, 1) == pdPASS) {
if(audioRxTaskMessage.cmd == SET_VOLUME){
audioTxTaskMessage.cmd = SET_VOLUME;
audio.setVolume(audioRxTaskMessage.value);
audioTxTaskMessage.ret = 1;
xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
}
else if(audioRxTaskMessage.cmd == CONNECTTOHOST){
audioTxTaskMessage.cmd = CONNECTTOHOST;
audioTxTaskMessage.ret = audio.connecttohost(audioRxTaskMessage.txt);
xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
}
else if(audioRxTaskMessage.cmd == CONNECTTOSD){
audioTxTaskMessage.cmd = CONNECTTOSD;
audioTxTaskMessage.ret = audio.connecttoSD(audioRxTaskMessage.txt);
xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
}
else if(audioRxTaskMessage.cmd == GET_VOLUME){
audioTxTaskMessage.cmd = GET_VOLUME;
audioTxTaskMessage.ret = audio.getVolume();
xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
}
else{
log_i("error");
}
}
audio.loop();
}
}
void audioInit() {
xTaskCreatePinnedToCore(
audioTask, /* Function to implement the task */
"audioplay", /* Name of the task */
5000, /* Stack size in words */
NULL, /* Task input parameter */
2 | portPRIVILEGE_BIT, /* Priority of the task */
NULL, /* Task handle. */
1 /* Core where the task should run */
);
}
audioMessage transmitReceive(audioMessage msg){
xQueueSend(audioSetQueue, &msg, portMAX_DELAY);
if(xQueueReceive(audioGetQueue, &audioRxMessage, portMAX_DELAY) == pdPASS){
if(msg.cmd != audioRxMessage.cmd){
log_e("wrong reply from message queue");
}
}
return audioRxMessage;
}
void audioSetVolume(uint8_t vol){
audioTxMessage.cmd = SET_VOLUME;
audioTxMessage.value = vol;
audioMessage RX = transmitReceive(audioTxMessage);
}
uint8_t audioGetVolume(){
audioTxMessage.cmd = GET_VOLUME;
audioMessage RX = transmitReceive(audioTxMessage);
return RX.ret;
}
bool audioConnecttohost(const char* host){
audioTxMessage.cmd = CONNECTTOHOST;
audioTxMessage.txt = host;
audioMessage RX = transmitReceive(audioTxMessage);
return RX.ret;
}
bool audioConnecttoSD(const char* filename){
audioTxMessage.cmd = CONNECTTOSD;
audioTxMessage.txt = filename;
audioMessage RX = transmitReceive(audioTxMessage);
return RX.ret;
}
//****************************************************************************************
// S E T U P *
//****************************************************************************************
void setup() {
Serial.begin(115200);
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED) delay(1500);
audioInit();
audioConnecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3");
audioSetVolume(15);
log_i("current volume is: %d", audioGetVolume());
}
//****************************************************************************************
// L O O P *
//****************************************************************************************
void loop(){
// your own code here
}
//*****************************************************************************************
// E V E N T S *
//*****************************************************************************************
void audio_info(const char *info){
Serial.print("info "); Serial.println(info);
}

View File

@ -0,0 +1,58 @@
//**********************************************************************************************************
//* audioI2S-- I2S audiodecoder for ESP32, SdFat example *
//**********************************************************************************************************
//
// first release on 05/2020
// updated on Sep. 27, 2021
/*
⒈ install SdFat V2 from https://github.com/greiman/SdFat
⒉ activate "SDFATFS_USED" in Audio.h
⒊ activate "#define USE_UTF8_LONG_NAMES 1" in SdFatConfig.h
*/
#include "Arduino.h"
#include "Audio.h"
#include "SPI.h"
// 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
Audio audio;
void setup() {
pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
SPI.setFrequency(1000000);
Serial.begin(115200);
SD.begin(SD_CS);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(12); // 0...21
// audio.connecttoFS(SD, "test.mp3");
audio.connecttoFS(SD, "良い一日私の友達.mp3");
}
void loop()
{
audio.loop();
}
// 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);
}

View File

@ -0,0 +1,224 @@
#include <Arduino.h>
#include <Preferences.h>
#include <SPI.h>
#include <WiFi.h>
#include "tft.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-TFT-Library-ILI9486"
#include "Audio.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-audioI2S"
#define TFT_CS 22
#define TFT_DC 21
#define TP_CS 14 //16
#define TP_IRQ 39
#define SPI_MOSI 23
#define SPI_MISO 19
#define SPI_SCK 18
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26
Preferences pref;
TFT tft;
TP tp(TP_CS, TP_IRQ);
Audio audio;
String ssid = "*****";
String password = "*****";
String stations[] ={
"0n-80s.radionetz.de:8000/0n-70s.mp3",
"mediaserv30.live-streams.nl:8000/stream",
"www.surfmusic.de/m3u/100-5-das-hitradio,4529.m3u",
"stream.1a-webradio.de/deutsch/mp3-128/vtuner-1a",
"mp3.ffh.de/radioffh/hqlivestream.aac", // 128k aac
"www.antenne.de/webradio/antenne.m3u",
"listen.rusongs.ru/ru-mp3-128",
"edge.audio.3qsdn.com/senderkw-mp3",
"macslons-irish-pub-radio.com/media.asx",
};
//some global variables
uint8_t max_volume = 21;
uint8_t max_stations = 0; //will be set later
uint8_t cur_station = 0; //current station(nr), will be set later
uint8_t cur_volume = 0; //will be set from stored preferences
int8_t cur_btn =-1; //current button (, -1 means idle)
enum action{VOLUME_UP=0, VOLUME_DOWN=1, STATION_UP=2, STATION_DOWN=3};
enum staus {RELEASED=0, PRESSED=1};
struct _btns{
uint16_t x; //PosX
uint16_t y; //PosY
uint16_t w; //Width
uint16_t h; //Hight
uint8_t a; //Action
uint8_t s; //Status
};
typedef _btns btns;
btns btn[4];
//**************************************************************************************************
// G U I *
//**************************************************************************************************
void draw_button(btns b){
uint16_t color=TFT_BLACK;
uint8_t r=4, o=r*3;
if(b.s==RELEASED) color=TFT_GOLD;
if(b.s==PRESSED) color=TFT_DEEPSKYBLUE;
tft.drawRoundRect(b.x, b.y, b.w, b.h, r, color);
switch(b.a){
case VOLUME_UP:
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;
case VOLUME_DOWN:
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;
case STATION_UP:
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;
case STATION_DOWN:
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;
}
}
void write_stationNr(uint8_t nr){
tft.fillRect(80, 250, 80, 60, TFT_BLACK);
String snr = String(nr);
if(snr.length()<2) snr = "0"+snr;
tft.setCursor(98, 255);
tft.setFont(Times_New_Roman66x53);
tft.setTextColor(TFT_YELLOW);
tft.print(snr);
}
void write_volume(uint8_t vol){
tft.fillRect(320, 250, 80, 60, TFT_BLACK);
String svol = String(vol);
if(svol.length()<2) svol = "0"+svol;
tft.setCursor(338, 255);
tft.setFont(Times_New_Roman66x53);
tft.setTextColor(TFT_YELLOW);
tft.print(svol);
}
void write_stationName(String sName){
tft.fillRect(0, 0, 480, 100, TFT_BLACK);
tft.setFont(Times_New_Roman43x35);
tft.setTextColor(TFT_CORNSILK);
tft.setCursor(20, 20);
tft.print(sName);
}
void write_streamTitle(String sTitle){
tft.fillRect(0, 100, 480, 150, TFT_BLACK);
tft.setFont(Times_New_Roman43x35);
tft.setTextColor(TFT_LIGHTBLUE);
tft.setCursor(20, 100);
int l = tft.writeText((const uint8_t*) sTitle.c_str(), 100 + 150); // do not write under y=250
if(l < sTitle.length()){
// sTitle has been shortened, is too long for the display
}
}
//**************************************************************************************************
// S E T U P *
//**************************************************************************************************
void setup() {
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;
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;
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;
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;
max_stations= sizeof(stations)/sizeof(stations[0]); log_i("max stations %i", max_stations);
Serial.begin(115200);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
pref.begin("WebRadio", false); // instance of preferences for defaults (station, volume ...)
if(pref.getShort("volume", 1000) == 1000){ // if that: pref was never been initialized
pref.putShort("volume", 10);
pref.putShort("station", 0);
}
else{ // get the stored values
cur_station = pref.getShort("station");
cur_volume = pref.getShort("volume");
}
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED){
delay(2000);
Serial.print(".");
}
log_i("Connect to %s", WiFi.SSID().c_str());
tft.begin(TFT_CS, TFT_DC, SPI_MOSI, SPI_MISO, SPI_SCK);
tft.setRotation(3);
tp.setRotation(3);
tft.setFont(Times_New_Roman43x35);
tft.fillScreen(TFT_BLACK);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(cur_volume); // 0...21
audio.connecttohost(stations[cur_station].c_str());
for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++) draw_button(btn[i]);
write_volume(cur_volume);
write_stationNr(cur_station);
}
//**************************************************************************************************
// L O O P *
//**************************************************************************************************
void loop()
{
audio.loop();
tp.loop();
}
//**************************************************************************************************
// E V E N T S *
//**************************************************************************************************
void audio_info(const char *info){
Serial.print("audio_info: "); Serial.println(info);
}
void audio_showstation(const char *info){
write_stationName(String(info));
}
void audio_showstreamtitle(const char *info){
String sinfo=String(info);
sinfo.replace("|", "\n");
write_streamTitle(sinfo);
}
void tp_pressed(uint16_t x, uint16_t y){
for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++){
if(x>btn[i].x && (x<btn[i].x+btn[i].w)){
if(y>btn[i].y && (y<btn[i].y+btn[i].h)){
cur_btn=i;
btn[cur_btn].s=PRESSED;
draw_button(btn[cur_btn]);
}
}
}
}
void tp_released(){
if(cur_btn !=-1){
btn[cur_btn].s=RELEASED;
draw_button(btn[cur_btn]);
switch(btn[cur_btn].a){
case VOLUME_UP: if(cur_volume<max_volume){
cur_volume++;
write_volume(cur_volume);
audio.setVolume(cur_volume);
pref.putShort("volume", cur_volume);} // store the current volume in nvs
break;
case VOLUME_DOWN: if(cur_volume>0){
cur_volume-- ;
write_volume(cur_volume);
audio.setVolume(cur_volume);
pref.putShort("volume", cur_volume);} // store the current volume in nvs
break;
case STATION_UP: if(cur_station<max_stations-1){
cur_station++;
write_stationNr(cur_station);
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
audio.connecttohost(stations[cur_station].c_str());
pref.putShort("station", cur_station);} // store the current station in nvs
break;
case STATION_DOWN:if(cur_station>0){
cur_station--;
write_stationNr(cur_station);
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
audio.connecttohost(stations[cur_station].c_str());
pref.putShort("station", cur_station);} // store the current station in nvs
break;
}
}
cur_btn=-1;
}

View File

@ -0,0 +1,269 @@
// this is the same example as Webradio_I2S.ino only with an IR remote control
#include <Arduino.h>
#include <Preferences.h>
#include <SPI.h>
#include <WiFi.h>
#include "tft.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-TFT-Library-ILI9486"
#include "Audio.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-audioI2S"
#include "IR.h" //see my repository at github "ESP32-IR-Remote-Control"
#define TFT_CS 22
#define TFT_DC 21
#define TP_CS 16
#define TP_IRQ 39
#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 IR_PIN 34
Preferences pref;
TFT tft; // @suppress("Abstract class cannot be instantiated")
TP tp(TP_CS, TP_IRQ);
Audio audio;
IR ir(IR_PIN); // do not change the objectname, it must be "ir"
String ssid = "*********";
String password = "*********";
String stations[] ={
"0n-80s.radionetz.de:8000/0n-70s.mp3",
"mediaserv30.live-streams.nl:8000/stream",
"www.surfmusic.de/m3u/100-5-das-hitradio,4529.m3u",
"stream.1a-webradio.de/deutsch/mp3-128/vtuner-1a",
"mp3.ffh.de/radioffh/hqlivestream.aac", // 128k aac
"www.antenne.de/webradio/antenne.m3u",
"listen.rusongs.ru/ru-mp3-128",
"edge.audio.3qsdn.com/senderkw-mp3",
"macslons-irish-pub-radio.com/media.asx",
};
//some global variables
uint8_t max_volume = 21;
uint8_t max_stations = 0; //will be set later
uint8_t cur_station = 0; //current station(nr), will be set later
uint8_t cur_volume = 0; //will be set from stored preferences
int8_t cur_btn =-1; //current button (, -1 means idle)
enum action{VOLUME_UP=0, VOLUME_DOWN=1, STATION_UP=2, STATION_DOWN=3};
enum staus {RELEASED=0, PRESSED=1};
struct _btns{
uint16_t x; //PosX
uint16_t y; //PosY
uint16_t w; //Width
uint16_t h; //Hight
uint8_t a; //Action
uint8_t s; //Status
};
typedef _btns btns;
btns btn[4];
//**************************************************************************************************
// G U I *
//**************************************************************************************************
void draw_button(btns b){
uint16_t color=TFT_BLACK;
uint8_t r=4, o=r*3;
if(b.s==RELEASED) color=TFT_GOLD;
if(b.s==PRESSED) color=TFT_DEEPSKYBLUE;
tft.drawRoundRect(b.x, b.y, b.w, b.h, r, color);
switch(b.a){
case VOLUME_UP:
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;
case VOLUME_DOWN:
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;
case STATION_UP:
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;
case STATION_DOWN:
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;
}
}
void write_stationNr(uint8_t nr){
tft.fillRect(80, 250, 80, 60, TFT_BLACK);
String snr = String(nr);
if(snr.length()<2) snr = "0"+snr;
tft.setCursor(98, 255);
tft.setFont(Times_New_Roman66x53);
tft.setTextColor(TFT_YELLOW);
tft.print(snr);
}
void write_volume(uint8_t vol){
tft.fillRect(320, 250, 80, 60, TFT_BLACK);
String svol = String(vol);
if(svol.length()<2) svol = "0"+svol;
tft.setCursor(338, 255);
tft.setFont(Times_New_Roman66x53);
tft.setTextColor(TFT_YELLOW);
tft.print(svol);
}
void write_stationName(String sName){
tft.fillRect(0, 0, 480, 100, TFT_BLACK);
tft.setFont(Times_New_Roman43x35);
tft.setTextColor(TFT_CORNSILK);
tft.setCursor(20, 20);
tft.print(sName);
}
void write_streamTitle(String sTitle){
tft.fillRect(0, 100, 480, 150, TFT_BLACK);
tft.setFont(Times_New_Roman43x35);
tft.setTextColor(TFT_LIGHTBLUE);
tft.setCursor(20, 100);
tft.print(sTitle);
}
void volume_up(){
if(cur_volume < max_volume){
cur_volume++;
write_volume(cur_volume);
audio.setVolume(cur_volume);
pref.putShort("volume", cur_volume);} // store the current volume in nvs
}
void volume_down(){
if(cur_volume>0){
cur_volume-- ;
write_volume(cur_volume);
audio.setVolume(cur_volume);
pref.putShort("volume", cur_volume);} // store the current volume in nvs
}
void station_up(){
if(cur_station < max_stations-1){
cur_station++;
write_stationNr(cur_station);
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
audio.connecttohost(stations[cur_station].c_str());
pref.putShort("station", cur_station);} // store the current station in nvs
}
void station_down(){
if(cur_station > 0){
cur_station--;
write_stationNr(cur_station);
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
audio.connecttohost(stations[cur_station].c_str());
pref.putShort("station", cur_station);} // store the current station in nvs
}
//**************************************************************************************************
// S E T U P *
//**************************************************************************************************
void setup() {
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;
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;
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;
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;
max_stations= sizeof(stations)/sizeof(stations[0]); log_i("max stations %i", max_stations);
Serial.begin(115200);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
pref.begin("WebRadio", false); // instance of preferences for defaults (station, volume ...)
if(pref.getShort("volume", 1000) == 1000){ // if that: pref was never been initialized
pref.putShort("volume", 10);
pref.putShort("station", 0);
}
else{ // get the stored values
cur_station = pref.getShort("station");
cur_volume = pref.getShort("volume");
}
WiFi.disconnect();
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED) {delay(1500); Serial.print(".");}
log_i("Connected to %s", WiFi.SSID().c_str());
tft.begin(TFT_CS, TFT_DC, SPI_MOSI, SPI_MISO, SPI_SCK);
tft.setFrequency(20000000);
tft.setRotation(3);
tp.setRotation(3);
tft.setFont(Times_New_Roman43x35);
tft.fillScreen(TFT_BLACK);
ir.begin(); // Init InfraredDecoder
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(cur_volume); // 0...21
audio.connecttohost(stations[cur_station].c_str());
for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++) draw_button(btn[i]);
write_volume(cur_volume);
write_stationNr(cur_station);
}
//**************************************************************************************************
// L O O P *
//**************************************************************************************************
void loop()
{
audio.loop();
tp.loop();
ir.loop();
}
//**************************************************************************************************
// E V E N T S *
//**************************************************************************************************
void audio_info(const char *info){
Serial.print("audio_info: "); Serial.println(info);
}
void audio_showstation(const char *info){
write_stationName(String(info));
}
void audio_showstreamtitle(const char *info){
String sinfo=String(info);
sinfo.replace("|", "\n");
write_streamTitle(sinfo);
}
void tp_pressed(uint16_t x, uint16_t y){
for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++){
if(x>btn[i].x && (x<btn[i].x+btn[i].w)){
if(y>btn[i].y && (y<btn[i].y+btn[i].h)){
cur_btn=i;
btn[cur_btn].s=PRESSED;
draw_button(btn[cur_btn]);
}
}
}
}
void tp_released(){
if(cur_btn !=-1){
btn[cur_btn].s=RELEASED;
draw_button(btn[cur_btn]);
switch(btn[cur_btn].a){
case VOLUME_UP: volume_up(); break;
case VOLUME_DOWN: volume_down(); break;
case STATION_UP: station_up(); break;
case STATION_DOWN: station_down(); break;
}
}
cur_btn=-1;
}
// Events from IR Library
void ir_res(uint32_t res){
if(res < max_stations){
cur_station = res;
write_stationNr(cur_station);
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
audio.connecttohost(stations[cur_station].c_str());
pref.putShort("station", cur_station);} // store the current station in nvs
else{
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
audio.connecttohost(stations[cur_station].c_str());
}
}
void ir_number(const char* num){
tft.fillRect(0, 0, 480, 250, TFT_BLACK);
tft.setTextSize(7);
tft.setTextColor(TFT_CORNSILK);
tft.setCursor(50, 70);
tft.print(num);
}
void ir_key(const char* key){
switch(key[0]){
case 'k': break; // OK
case 'r': volume_up(); break; // right
case 'l': volume_down(); break; // left
case 'u': station_up(); break; // up
case 'd': station_down(); break; // down
case '#': break; // #
case '*': break; // *
default: break;
}
}

View File

@ -0,0 +1,86 @@
// Copied from https://github.com/LilyGO/TTGO-TAudio/issues/12
// Required Libraries (Download zips and add to the Arduino IDE library).
#include "Arduino.h"
#include <WM8978.h> // https://github.com/CelliesProjects/wm8978-esp32
#include <Audio.h> // https://github.com/schreibfaul1/ESP32-audioI2S
// T-Audio 1.6 WM8978 I2C pins.
#define I2C_SDA 19
#define I2C_SCL 18
// T-Audio 1.6 WM8978 I2S pins.
#define I2S_BCK 33
#define I2S_WS 25
#define I2S_DOUT 26
// T-Audio 1.6 WM8978 MCLK gpio number
#define I2S_MCLKPIN 0
Audio audio;
WM8978 dac;
void setup() {
Serial.begin(115200);
// Setup wm8978 I2C interface.
if (!dac.begin(I2C_SDA, I2C_SCL)) {
ESP_LOGE(TAG, "Error setting up dac: System halted.");
while (1) delay(100);
}
// Select I2S pins
audio.setPinout(I2S_BCK, I2S_WS, I2S_DOUT);
audio.i2s_mclk_pin_select(I2S_MCLKPIN);
// WiFi Settings here.
WiFi.begin("EnterSSIDHere", "EnterPasswordHere");
while (!WiFi.isConnected()) {
delay(10);
}
ESP_LOGI(TAG, "Connected. Starting MP3...");
// Enter your Icecast station URL here.
audio.setVolume(21);
audio.connecttohost("http://hestia2.cdnstream.com/1458_128");
// Volume control.
dac.setSPKvol(63); // Change volume here for board speaker output (Max 63).
dac.setHPvol(63, 63); // Change volume here for headphone jack left, right channel.
}
void loop() {
// Start the stream.
audio.loop();
}
// 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);
}

View File

@ -0,0 +1,68 @@
#include "Arduino.h"
#include "Audio.h"
#include "SD.h"
#include "SPI.h"
#include "FS.h"
#include "Ticker.h"
// 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
Audio audio;
Ticker ticker;
struct tm timeinfo;
time_t now;
uint8_t hour = 6;
uint8_t minute = 59;
uint8_t sec = 45;
bool f_time = false;
int8_t timefile = -1;
char chbuf[100];
void tckr1s(){
sec++;
if(sec > 59) {sec = 0; minute++;}
if(minute > 59){minute = 0; hour++;}
if(hour > 23) {hour = 0;}
if(minute == 59 && sec == 50) f_time = true; // flag will be set 10s before full hour
Serial.printf("%02d:%02d:%02d\n", hour, minute, sec);
}
void setup() {
Serial.begin(115200);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
SD.begin(SD_CS);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(10); // 0...21
ticker.attach(1, tckr1s);
}
void loop(){
audio.loop();
if(f_time == true){
f_time = false;
timefile = 3;
uint8_t next_hour = hour + 1;
if(next_hour == 25) next_hour = 1;
sprintf(chbuf, "/voice_time/%03d.mp3", next_hour);
audio.connecttoFS(SD, chbuf);
}
}
void audio_eof_mp3(const char *info){ //end of file
//Serial.printf("file :%s\n", info);
if(timefile>0){
if(timefile==1){audio.connecttoFS(SD, "/voice_time/080.mp3"); timefile--;} // stroke
if(timefile==2){audio.connecttoFS(SD, "/voice_time/200.mp3"); timefile--;} // precisely
if(timefile==3){audio.connecttoFS(SD, "/voice_time/O'clock.mp3"); timefile--;}
}
}