From a91beeb0cf79084e159890ac25044a00003ceb5a Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Tue, 9 Feb 2021 15:47:20 +0100
Subject: [PATCH] Add support for transistor-based output without DAC
Add support for transistor-based output without DAC (#10875)
---
tasmota/tasmota_configurations_ESP32.h | 4 +-
tasmota/xdrv_42_i2s_audio.ino | 134 +++++++++++++++----------
2 files changed, 83 insertions(+), 55 deletions(-)
diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/tasmota_configurations_ESP32.h
index af6d0418f..f4dc57b82 100644
--- a/tasmota/tasmota_configurations_ESP32.h
+++ b/tasmota/tasmota_configurations_ESP32.h
@@ -79,8 +79,8 @@
#define FALLBACK_MODULE M5STACK_CORE2 // [Module2] Select default module on fast reboot where USER_MODULE is user template
#define USE_M5STACK_CORE2 // Add support for M5Stack Core2
- #define SAY_TIME
- #define USE_WEBRADIO
+ #define USE_I2S_SAY_TIME
+ #define USE_I2S_WEBRADIO
#define USE_MPU6886
#define USE_UFILESYS
#define USE_SDCARD
diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino
index 359308cba..a63918206 100644
--- a/tasmota/xdrv_42_i2s_audio.ino
+++ b/tasmota/xdrv_42_i2s_audio.ino
@@ -1,5 +1,5 @@
/*
- xdrv_42_i2s_audio.ino - audio dac support for Tasmota
+ xdrv_42_i2s_audio.ino - Audio dac support for Tasmota
Copyright (C) 2021 Gerhard Mutz and Theo Arends
@@ -17,16 +17,39 @@
along with this program. If not, see .
*/
-#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
+#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
+/*********************************************************************************************\
+ * I2S support using an external DAC or a speaker connected to GPIO03 using a transistor
+ *
+ * Uses fixed GPIOs for ESP8266:
+ * I2S Out Data GPIO03 (Rx)
+ * I2S Out Bit Clock GPIO15
+ * I2S Out Word Select GPIO02
+ * I2S In Data GPIO12
+ * I2S In Bit Clock GPIO13
+ * I2S In Word Select GPIO14
+\*********************************************************************************************/
+
+#define XDRV_42 42
+
+#define USE_I2S_EXTERNAL_DAC 1
+//#define USE_I2S_NO_DAC // Add support for transistor-based output without DAC
+//#define USE_I2S_WEBRADIO // Add support for web radio
+//#define USE_I2S_SAY_TIME // Add support for english speaking clock
+
#include "AudioFileSourcePROGMEM.h"
#include "AudioFileSourceID3.h"
#include "AudioGeneratorMP3.h"
-#include "AudioOutputI2S.h"
+#ifdef USE_I2S_NO_DAC
+ #include "AudioOutputI2SNoDAC.h" // Transistor-driven lower quality connected to RX pin
+#else
+ #include "AudioOutputI2S.h" // External I2S DAC IC
+#endif // USE_I2S_NO_DAC
#include
#include "AudioFileSourceFS.h"
-#ifdef SAY_TIME
-#include "AudioGeneratorTalkie.h"
-#endif
+#ifdef USE_I2S_SAY_TIME
+ #include "AudioGeneratorTalkie.h"
+#endif // USE_I2S_SAY_TIME
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorAAC.h"
@@ -41,7 +64,7 @@
#undef AUDIO_PWR_OFF
#define AUDIO_PWR_ON TTGO_audio_power(true);
#define AUDIO_PWR_OFF TTGO_audio_power(false);
-#endif // USE_TTGO_WATCH
+#endif // USE_TTGO_WATCH
#ifdef USE_M5STACK_CORE2
#undef AUDIO_PWR_ON
@@ -54,21 +77,19 @@
#define DAC_IIS_BCK 12
#define DAC_IIS_WS 0
#define DAC_IIS_DOUT 2
-#endif // USE_M5STACK_CORE2
-
-
-#define EXTERNAL_DAC_PLAY 1
-
-#define XDRV_42 42
+#endif // USE_M5STACK_CORE2
AudioGeneratorMP3 *mp3 = nullptr;
AudioFileSourceFS *file;
-AudioOutputI2S *out;
+#ifdef USE_I2S_NO_DAC
+ AudioOutputI2SNoDAC *out;
+#else
+ AudioOutputI2S *out;
+#endif // USE_I2S_NO_DAC
AudioFileSourceID3 *id3;
AudioGeneratorMP3 *decoder = NULL;
void *mp3ram = NULL;
-
extern FS *ufsp;
#ifdef ESP8266
@@ -81,7 +102,7 @@ const int preallocateCodecSize = 29192; // MP3 codec max mem needed
//const int preallocateCodecSize = 85332; // AAC+SBR codec max mem needed
#endif // ESP32
-#ifdef USE_WEBRADIO
+#ifdef USE_I2S_WEBRADIO
AudioFileSourceICYStream *ifile = NULL;
AudioFileSourceBuffer *buff = NULL;
char wr_title[64];
@@ -90,11 +111,11 @@ char wr_title[64];
void *preallocateBuffer = NULL;
void *preallocateCodec = NULL;
uint32_t retryms = 0;
-#endif // USE_WEBRADIO
+#endif // USE_I2S_WEBRADIO
-#ifdef SAY_TIME
+#ifdef USE_I2S_SAY_TIME
AudioGeneratorTalkie *talkie = nullptr;
-#endif // SAY_TIME
+#endif // USE_I2S_SAY_TIME
//! MAX98357A + INMP441 DOUBLE I2S BOARD
#ifdef ESP8266
@@ -111,26 +132,26 @@ AudioGeneratorTalkie *talkie = nullptr;
#ifndef DAC_IIS_BCK
#undef DAC_IIS_BCK
#define DAC_IIS_BCK 26
-#endif // DAC_IIS_BCK
+#endif // DAC_IIS_BCK
#ifndef DAC_IIS_WS
#undef DAC_IIS_WS
#define DAC_IIS_WS 25
-#endif // DAC_IIS_WS
+#endif // DAC_IIS_WS
#ifndef DAC_IIS_DOUT
#undef DAC_IIS_DOUT
#define DAC_IIS_DOUT 33
-#endif // DAC_IIS_DOUT
+#endif // DAC_IIS_DOUT
#ifndef DAC_IIS_DIN
#undef DAC_IIS_DIN
-#define DAC_IIS_DIN 34
-#endif // DAC_IIS_DIN
+#define DAC_IIS_DIN 34
+#endif // DAC_IIS_DIN
#endif // ESP32
-#ifdef SAY_TIME
+#ifdef USE_I2S_SAY_TIME
long timezone = 2;
byte daysavetime = 1;
@@ -229,21 +250,29 @@ void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) {
out->stop();
AUDIO_PWR_OFF
}
-#endif // SAY_TIME
+#endif // USE_I2S_SAY_TIME
// should be in settings
uint8_t is2_volume;
void I2S_Init(void) {
-#if EXTERNAL_DAC_PLAY
- out = new AudioOutputI2S();
+#if USE_I2S_EXTERNAL_DAC
+ #ifdef USE_I2S_NO_DAC
+ out = new AudioOutputI2SNoDAC();
+ #else
+ out = new AudioOutputI2S();
+ #endif // USE_I2S_NO_DAC
#ifdef ESP32
- out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT);
+ out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT);
#endif // ESP32
#else
- out = new AudioOutputI2S(0, 1);
-#endif // EXTERNAL_DAC_PLAY
+ #ifdef USE_I2S_NO_DAC
+ out = new AudioOutputI2SNoDAC();
+ #else
+ out = new AudioOutputI2S(0, 1); // Internal DAC port 0
+ #endif // USE_I2S_NO_DAC
+#endif // USE_I2S_EXTERNAL_DAC
is2_volume=10;
out->SetGain(((float)is2_volume/100.0)*4.0);
@@ -255,7 +284,7 @@ void I2S_Init(void) {
mp3ram = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
-#ifdef USE_WEBRADIO
+#ifdef USE_I2S_WEBRADIO
if (psramFound()) {
preallocateBuffer = heap_caps_malloc(preallocateBufferSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
preallocateCodec = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
@@ -266,12 +295,11 @@ void I2S_Init(void) {
if (!preallocateBuffer || !preallocateCodec) {
//Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize+preallocateCodecSize);
}
-#endif // USE_WEBRADIO
-#endif // ESP32
+#endif // USE_I2S_WEBRADIO
+#endif // ESP32
}
-
#ifdef ESP32
#define MODE_MIC 0
#define MODE_SPK 1
@@ -426,7 +454,7 @@ bool SaveWav(char *path, uint8_t *buff, uint32_t size) {
return true;
}
-#endif // ESP32
+#endif // ESP32
#ifdef ESP32
TaskHandle_t mp3_task_h;
@@ -447,9 +475,9 @@ void mp3_task(void *arg) {
}
}
}
-#endif // ESP32
+#endif // ESP32
-#ifdef USE_WEBRADIO
+#ifdef USE_I2S_WEBRADIO
void MDCallback(void *cbData, const char *type, bool isUnicode, const char *str) {
const char *ptr = reinterpret_cast(cbData);
(void) isUnicode; // Punt this ball for now
@@ -557,7 +585,7 @@ void Cmd_MicRec(void) {
ResponseCmndChar(XdrvMailbox.data);
}
}
-#endif // USE_M5STACK_CORE2
+#endif // USE_M5STACK_CORE2
const char HTTP_WEBRADIO[] PROGMEM =
"{s}" "I2S_WR-Title" "{m}%s{e}";
@@ -568,7 +596,7 @@ void I2S_WR_Show(void) {
}
}
-#endif
+#endif // USE_I2S_WEBRADIO
#ifdef ESP32
void Play_mp3(const char *path) {
@@ -610,7 +638,7 @@ void Play_mp3(const char *path) {
mp3_delete();
}
-#endif // USE_SCRIPT
+#endif // USE_SCRIPT
}
void mp3_delete(void) {
@@ -620,7 +648,7 @@ void mp3_delete(void) {
mp3=nullptr;
AUDIO_PWR_OFF
}
-#endif // ESP32
+#endif // ESP32
void Say(char *text) {
@@ -642,22 +670,22 @@ const char kI2SAudio_Commands[] PROGMEM = "I2S|"
"Say|Gain|Time"
#ifdef ESP32
"|Play"
-#ifdef USE_WEBRADIO
+#ifdef USE_I2S_WEBRADIO
"|WR"
-#endif // USE_WEBRADIO
+#endif // USE_I2S_WEBRADIO
#ifdef USE_M5STACK_CORE2
"|REC"
-#endif // USE_M5STACK_CORE2
-#endif // ESP32
+#endif // USE_M5STACK_CORE2
+#endif // ESP32
;
void (* const I2SAudio_Command[])(void) PROGMEM = {
&Cmd_Say, &Cmd_Gain, &Cmd_Time
#ifdef ESP32
,&Cmd_Play
-#ifdef USE_WEBRADIO
+#ifdef USE_I2S_WEBRADIO
,&Cmd_WebRadio
-#endif // USE_WEBRADIO
+#endif // USE_I2S_WEBRADIO
#ifdef USE_M5STACK_CORE2
,&Cmd_MicRec
#endif // USE_M5STACK_CORE2
@@ -691,9 +719,9 @@ void Cmd_Say(void) {
}
void Cmd_Time(void) {
-#ifdef SAY_TIME
+#ifdef USE_I2S_SAY_TIME
sayTime(RtcTime.hour, RtcTime.minute, talkie);
-#endif // SAY_TIME
+#endif // USE_I2S_SAY_TIME
ResponseCmndDone();
}
@@ -712,12 +740,12 @@ bool Xdrv42(uint8_t function) {
I2S_Init();
break;
#ifdef USE_WEBSERVER
-#ifdef USE_WEBRADIO
+#ifdef USE_I2S_WEBRADIO
case FUNC_WEB_SENSOR:
I2S_WR_Show();
break;
-#endif // USE_WEBRADIO
-#endif // USE_WEBSERVER
+#endif // USE_I2S_WEBRADIO
+#endif // USE_WEBSERVER
}
return result;
}