Add support for transistor-based output without DAC

Add support for transistor-based output without DAC (#10875)
This commit is contained in:
Theo Arends 2021-02-09 15:47:20 +01:00
parent 5663ce7788
commit a91beeb0cf
2 changed files with 83 additions and 55 deletions

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <ESP8266SAM.h>
#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<const char *>(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;
}