diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b42464e81a6..fc8a5995f54f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - ESP32 Framework (Arduino Core) from v2.0.12 to v2.0.13 ### Fixed +- ESP32 DS18x20 driver support extended over GPIO33 ### Removed @@ -37,7 +38,6 @@ All notable changes to this project will be documented in this file. - Support for IPv6 link-local zones for esp-idf 5.1 (necessary for Matter) - ESP32C3 relay click on restart - ## [13.1.0.1] 20230831 ### Added - Commands to allow setting of timeprop parameters (#19310) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b7593b5f653d..7b8a74f7c3c8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -122,7 +122,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Breaking Changed ### Changed -- ESP32 Framework (Arduino Core) from v2.0.12 to v2.0.13 +- ESP32 Framework (Arduino Core) from v2.0.11 to v2.0.13 - ESP32 LVGL library from v8.3.8 to v8.3.9 (no functional change) - Display invert setting after tasmota start in uDisplay driver [#19337](https://github.com/arendst/Tasmota/issues/19337) @@ -131,6 +131,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Teleinfo power [#19381](https://github.com/arendst/Tasmota/issues/19381) - Exception 3 in IRHVAC [#19389](https://github.com/arendst/Tasmota/issues/19389) - PCF8574 mode 1 with base relays exception 3/28 regression from v12.4.0.4 [#19408](https://github.com/arendst/Tasmota/issues/19408) +- ESP32 DS18x20 driver support extended over GPIO33 - ESP32 Support for IPv6 link-local zones for esp-idf 5.1 (necessary for Matter) - ESP32 Shutter migration [#19454](https://github.com/arendst/Tasmota/issues/19454) - ESP32 Shutter multi press button events [#19465](https://github.com/arendst/Tasmota/issues/19465) diff --git a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h index cb1e16d73132..77910ecb9673 100644 --- a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h +++ b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h @@ -159,27 +159,35 @@ static inline __attribute__((always_inline)) IO_REG_TYPE directRead(IO_REG_TYPE pin) { -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 // max. usable Pins are 23 for C6 (below flash pins) +// return digitalRead(pin); // Works most of the time +// return gpio_ll_get_level(&GPIO, pin); // The hal is not public api, don't use in application code + +//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if SOC_GPIO_PIN_COUNT <= 32 return (GPIO.in.val >> pin) & 0x1; -#else // plain ESP32 +#else // ESP32 with over 32 gpios if ( pin < 32 ) return (GPIO.in >> pin) & 0x1; - else if ( pin < 46 ) + else return (GPIO.in1.val >> (pin - 32)) & 0x1; #endif - return 0; + } static inline __attribute__((always_inline)) void directWriteLow(IO_REG_TYPE pin) { -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 +// digitalWrite(pin, 0); // Works most of the time +// gpio_ll_set_level(&GPIO, pin, 0); // The hal is not public api, don't use in application code + +//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if SOC_GPIO_PIN_COUNT <= 32 GPIO.out_w1tc.val = ((uint32_t)1 << pin); -#else // plain ESP32 +#else // ESP32 with over 32 gpios if ( pin < 32 ) GPIO.out_w1tc = ((uint32_t)1 << pin); - else if ( pin < 46 ) + else GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); #endif } @@ -187,66 +195,63 @@ void directWriteLow(IO_REG_TYPE pin) static inline __attribute__((always_inline)) void directWriteHigh(IO_REG_TYPE pin) { -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 +// digitalWrite(pin, 1); // Works most of the time +// gpio_ll_set_level(&GPIO, pin, 1); // The hal is not public api, don't use in application code + +//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if SOC_GPIO_PIN_COUNT <= 32 GPIO.out_w1ts.val = ((uint32_t)1 << pin); -#else // plain ESP32 +#else // ESP32 with over 32 gpios if ( pin < 32 ) GPIO.out_w1ts = ((uint32_t)1 << pin); - else if ( pin < 46 ) + else GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); #endif + } static inline __attribute__((always_inline)) void directModeInput(IO_REG_TYPE pin) { -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 - GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); -#else +// pinMode(pin, INPUT); // Too slow - doesn't work +// gpio_ll_output_disable(&GPIO, pin); // The hal is not public api, don't use in application code + if ( digitalPinIsValid(pin) ) { -#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4 - uint32_t rtc_reg(rtc_gpio_desc[pin].reg); - - if ( rtc_reg ) // RTC pins PULL settings - { - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); - } -#endif // Input +//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); +#else // ESP32 with over 32 gpios if ( pin < 32 ) GPIO.enable_w1tc = ((uint32_t)1 << pin); else GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); - } #endif + } + } static inline __attribute__((always_inline)) void directModeOutput(IO_REG_TYPE pin) { -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 - GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); -#else - if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs +// pinMode(pin, OUTPUT); // Too slow - doesn't work +// gpio_ll_output_enable(&GPIO, pin); // The hal is not public api, don't use in application code + + if ( digitalPinCanOutput(pin) ) { -#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4 - uint32_t rtc_reg(rtc_gpio_desc[pin].reg); - - if ( rtc_reg ) // RTC pins PULL settings - { - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); - } -#endif // Output +//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); +#else // ESP32 with over 32 gpios if ( pin < 32 ) GPIO.enable_w1ts = ((uint32_t)1 << pin); - else // already validated to pins <= 33 + else GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); - } #endif + } + } #define DIRECT_READ(base, pin) directRead(pin) @@ -254,7 +259,6 @@ void directModeOutput(IO_REG_TYPE pin) #define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) #define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) #define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) -//#warning "ESP32 OneWire testing" #elif defined(__SAMD21G18A__) #define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) diff --git a/lib/libesp32_audio/es7243e/src/es7243e.cpp b/lib/libesp32_audio/es7243e/src/es7243e.cpp index 38165ac5e7aa..7adda10cd639 100644 --- a/lib/libesp32_audio/es7243e/src/es7243e.cpp +++ b/lib/libesp32_audio/es7243e/src/es7243e.cpp @@ -28,7 +28,8 @@ #include "string.h" #include "esp_log.h" #include "rom/ets_sys.h" -#include "es7243e.h" + #include "es7243e.h" + static const char *TAG = "DRV7243E"; diff --git a/tasmota/tasmota_support/support_esp.ino b/tasmota/tasmota_support/support_esp.ino index 3d57f09cd3f5..6f3a8415dbdb 100644 --- a/tasmota/tasmota_support/support_esp.ino +++ b/tasmota/tasmota_support/support_esp.ino @@ -1132,13 +1132,6 @@ bool CanUsePSRAM(void) { if ((CHIP_ESP32 == chip_info.model) && (chip_revision < 300)) { return false; } -#if ESP_IDF_VERSION_MAJOR < 4 - uint32_t pkg_version = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG) & 0x7; - if ((CHIP_ESP32 == chip_info.model) && (pkg_version >= 6)) { - return false; // support for embedded PSRAM of ESP32-PICO-V3-02 requires esp-idf 4.4 - } -#endif // ESP_IDF_VERSION_MAJOR < 4 - #endif // CONFIG_IDF_TARGET_ESP32 return true; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino index 0c228a3ee9e9..98f45373e91e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino @@ -240,7 +240,7 @@ namespace { if (modelStr != kUnknownStr) { json.add(key, modelStr); } else { // Fallback to int value - json.add(key, model); + json.add(key, (int32_t)model); } } } // namespace { @@ -258,13 +258,13 @@ String sendACJsonState(const stdAc::state_t &state) { case stdAc::ac_command_t::kConfigCommand: // Note: for `kConfigCommand` the semantics of clock/sleep is abused IRremoteESP8266 lib-side for key/value pair // Ref: lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp[L3062-3066] - json.add(PSTR(D_JSON_IRHVAC_CONFIG_KEY), state.clock); - json.add(PSTR(D_JSON_IRHVAC_CONFIG_VALUE), state.sleep); + json.add(PSTR(D_JSON_IRHVAC_CONFIG_KEY), (int32_t)state.clock); + json.add(PSTR(D_JSON_IRHVAC_CONFIG_VALUE), (int32_t)state.sleep); break; case stdAc::ac_command_t::kTimerCommand: json.add(PSTR(D_JSON_IRHVAC_POWER), IRac::boolToString(state.power)); if(state.clock != -1) { json.add(PSTR(D_JSON_IRHVAC_CLOCK), irutils::minsToString(state.clock)); } - json.add(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); + json.add(PSTR(D_JSON_IRHVAC_SLEEP), (int32_t)state.sleep); break; case stdAc::ac_command_t::kControlCommand: default: @@ -288,8 +288,8 @@ String sendACJsonState(const stdAc::state_t &state) { json.add(PSTR(D_JSON_IRHVAC_FILTER), IRac::boolToString(state.filter)); json.add(PSTR(D_JSON_IRHVAC_CLEAN), IRac::boolToString(state.clean)); json.add(PSTR(D_JSON_IRHVAC_BEEP), IRac::boolToString(state.beep)); - json.add(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); - if(state.clock != -1) { json.add(PSTR(D_JSON_IRHVAC_CLOCK), state.clock); } + json.add(PSTR(D_JSON_IRHVAC_SLEEP), (int32_t)state.sleep); + if(state.clock != -1) { json.add(PSTR(D_JSON_IRHVAC_CLOCK), (int32_t)state.clock); } json.add(PSTR(D_JSON_IRHVAC_IFEEL), IRac::boolToString(state.iFeel)); addFloatToJson(json, PSTR(D_JSON_IRHVAC_SENSOR_TEMP), state.sensorTemperature, kNoTempValue); break; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino index 38eba8eff558..355928874127 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino @@ -42,11 +42,12 @@ #undef AUDIO_PWR_ON #undef AUDIO_PWR_OFF -#define AUDIO_PWR_ON -#define AUDIO_PWR_OFF +#define AUDIO_PWR_ON I2SAudioPower(true); +#define AUDIO_PWR_OFF I2SAudioPower(false); -#define USE_I2S_RTTTL +#define USE_I2S_SAY #define USE_I2S_SAY_TIME +#define USE_I2S_RTTTL /*********************************************************************************************\ * Driver Settings in memory @@ -96,7 +97,7 @@ typedef union { }; } BRIDGE_MODE; -class AudioOutputI2S; +class TasmotaAudioOutputI2S; struct AUDIO_I2S_t { tI2SSettings *Settings; @@ -106,7 +107,7 @@ struct AUDIO_I2S_t { AudioGeneratorMP3 *mp3 = nullptr; AudioFileSourceFS *file; - AudioOutputI2S *out; + TasmotaAudioOutputI2S *out; AudioFileSourceID3 *id3; AudioGeneratorMP3 *decoder = NULL; @@ -160,21 +161,20 @@ const int preallocateCodecSize = 29192; // MP3 codec max mem needed enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 }; void sayTime(int hour, int minutes); -void Cmd_MicRec(void); -void Cmd_wav2mp3(void); +void Cmndwav2mp3(void); void Cmd_Time(void); void Rtttl(char *buffer); -void Cmd_I2SRtttl(void); +void CmndI2SRtttl(void); /*********************************************************************************************\ * Class for outputting sound as endpoint for ESP8266Audio library \*********************************************************************************************/ -class AudioOutputI2S : public AudioOutput +class TasmotaAudioOutputI2S : public AudioOutput { public: - AudioOutputI2S(){ + TasmotaAudioOutputI2S(){ hertz = 16000; i2sOn = false; bps = I2S_DATA_BIT_WIDTH_16BIT; @@ -184,7 +184,7 @@ class AudioOutputI2S : public AudioOutput tx_is_enabled = false; } - ~AudioOutputI2S(){ + ~TasmotaAudioOutputI2S(){ if(i2sOn){ this->stop(); i2s_del_channel(tx_chan); @@ -572,6 +572,18 @@ int32_t I2sRecordShine(char *path) { /*********************************************************************************************\ * Driver Settings load and save using filesystem \*********************************************************************************************/ +// error codes +enum { + I2S_OK = 0, + I2S_ERR_OUTPUT_NOT_CONFIGURE, + I2S_ERR_DECODER_IN_USE, + I2S_ERR_FILE_NOT_FOUND, +}; + +// signal to an external Berry driver that we turn audio power on or off +void I2SAudioPower(bool power) { + callBerryEventDispatcher(PSTR("audio"), PSTR("power"), power, nullptr, 0); +} void I2SSettingsLoad(bool erase) { @@ -582,7 +594,7 @@ void I2SSettingsLoad(bool erase) { #else char filename[20]; // Use for drivers: - snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), XDRV_42); + snprintf_P(filename, sizeof(filename), TASM_FILE_DRIVER, XDRV_42); if (erase) { TfsDeleteFile(filename); // Use defaults } @@ -601,7 +613,7 @@ void I2SSettingsSave(void) { #ifdef USE_UFILESYS char filename[20]; // Use for drivers: - snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), XDRV_42); + snprintf_P(filename, sizeof(filename), TASM_FILE_DRIVER, XDRV_42); if (TfsSaveFile(filename, (const uint8_t*)audio_i2s.Settings, sizeof(tI2SSettings))) { AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: I2S saved to file")); } else { @@ -616,8 +628,8 @@ void I2SSettingsSave(void) { \*********************************************************************************************/ void I2sCheckCfg(void){ - bool useDuplexMode = ((Pin(GPIO_I2S_DIN) != -1) && (Pin(GPIO_I2S_DOUT) != -1)); // din and dout must be configured on port 0 for duplex - AddLog(LOG_LEVEL_DEBUG, PSTR("I2S: DIN %i , DOUT %i"),Pin(GPIO_I2S_DIN),Pin(GPIO_I2S_DOUT) ); + bool useDuplexMode = ((Pin(GPIO_I2S_DIN) != -1) && (Pin(GPIO_I2S_DOUT) != -1)); // din and dout must be configured on port 0 for full duplex + // AddLog(LOG_LEVEL_DEBUG, PSTR("I2S: DIN %i , DOUT %i"),Pin(GPIO_I2S_DIN),Pin(GPIO_I2S_DOUT) ); if(useDuplexMode){ if(audio_i2s.Settings->rx.mode == 1 || audio_i2s.Settings->tx.mode == 1 ){ useDuplexMode = false; @@ -663,7 +675,7 @@ bool I2sPinInit(void) { } if(audio_i2s.Settings->sys.tx == 1){ - audio_i2s.out = new AudioOutputI2S; + audio_i2s.out = new TasmotaAudioOutputI2S; int err = audio_i2s.out->SetPinout() ? 0 : 1; result += err; } @@ -754,7 +766,7 @@ void Webradio(const char *url) { if (audio_i2s.decoder || audio_i2s.mp3) return; if (!audio_i2s.out) return; if (audio_i2s.Settings->tx.webradio == 0) return; - AUDIO_PWR_ON + I2SAudioPower(true); audio_i2s.ifile = new AudioFileSourceICYStream(url); audio_i2s.ifile->RegisterMetadataCB(I2sMDCallback, NULL); audio_i2s.buff = new AudioFileSourceBuffer(audio_i2s.ifile, audio_i2s.preallocateBuffer, preallocateBufferSize); @@ -809,7 +821,7 @@ void I2sStopPlaying() { delete audio_i2s.ifile; audio_i2s.ifile = NULL; } - AUDIO_PWR_OFF + I2SAudioPower(false); } #ifdef USE_WEBSERVER @@ -827,25 +839,26 @@ void I2sWrShow(bool json) { } #endif // USE_WEBSERVER -void Play_mp3(const char *path) { - if (audio_i2s.decoder || audio_i2s.mp3) return; - if (!audio_i2s.out) return; - - FS *mp3fsp = ufsp; - if (!strncmp(path, "/ffs", 4)) { - path += 4; - mp3fsp = ffsp; - } +// Play_mp3 - Play a MP3 file from filesystem +// +// Returns I2S_error_t +int32_t I2SPlayMp3(const char *path) { + if (!audio_i2s.out) return I2S_ERR_OUTPUT_NOT_CONFIGURE; + if (audio_i2s.decoder || audio_i2s.mp3) return I2S_ERR_DECODER_IN_USE; - if (!mp3fsp->exists(path)) { - AddLog(LOG_LEVEL_INFO,PSTR("MP3-Title not found: %s"),path); - return; + // check if the filename starts with '/', if not add it + char fname[64]; + if (path[0] != '/') { + snprintf(fname, sizeof(fname), "/%s", path); + } else { + snprintf(fname, sizeof(fname), "%s", path); } + if (!ufsp->exists(fname)) { return I2S_ERR_FILE_NOT_FOUND; } - AUDIO_PWR_ON + I2SAudioPower(true); - audio_i2s.file = new AudioFileSourceFS(*mp3fsp, path); + audio_i2s.file = new AudioFileSourceFS(*ufsp, fname); audio_i2s.id3 = new AudioFileSourceID3(audio_i2s.file); @@ -858,6 +871,7 @@ void Play_mp3(const char *path) { // Always use a task xTaskCreatePinnedToCore(I2sMp3Task, "MP3", 8192, NULL, 3, &audio_i2s.mp3_task_handle, 1); + return I2S_OK; } void mp3_delete(void) { @@ -865,14 +879,14 @@ void mp3_delete(void) { delete audio_i2s.id3; delete audio_i2s.mp3; audio_i2s.mp3=nullptr; - AUDIO_PWR_OFF + I2SAudioPower(false); } void Say(char *text) { if (!audio_i2s.out) return; - AUDIO_PWR_ON + I2SAudioPower(true); ESP8266SAM *sam = new ESP8266SAM; @@ -880,7 +894,7 @@ void Say(char *text) { delete sam; audio_i2s.out->stop(); - AUDIO_PWR_OFF + I2SAudioPower(false); } /*********************************************************************************************\ @@ -888,26 +902,51 @@ void Say(char *text) { \*********************************************************************************************/ const char kI2SAudio_Commands[] PROGMEM = "I2S|" - "Say|Gain|Time|Rtttl|Play|WR|REC|MGain" + "Gain|Play|WR|Rec|MGain|Stop" +#ifdef USE_I2S_SAY + "|Say" +#ifdef USE_I2S_SAY_TIME + "|Time" +#endif // USE_I2S_SAY_TIME +#endif // USE_I2S_SAY + +#ifdef USE_I2S_RTTTL + "|Rtttl" +#endif #if defined(USE_SHINE) && defined(MP3_MIC_STREAM) - "|STREAM" + "|Stream" #endif // MP3_MIC_STREAM #ifdef I2S_BRIDGE - "|BRIDGE" + "|Bridge" #endif // I2S_BRIDGE ; void (* const I2SAudio_Command[])(void) PROGMEM = { - &Cmd_Say, &Cmd_Gain,&Cmd_Time,&Cmd_I2SRtttl,&Cmd_Play,&Cmd_WebRadio,&Cmd_MicRec,&Cmd_MicGain + &CmndI2SGain, &CmndI2SPlay, &CmndI2SWebRadio, &CmndI2SMicRec, &CmndI2SMicGain, &CmndI2SStop, +#ifdef USE_I2S_SAY + &CmndI2SSay, +#ifdef USE_I2S_SAY_TIME + &Cmd_Time, +#endif // USE_I2S_SAY_TIME +#endif // USE_I2S_SAY + +#ifdef USE_I2S_RTTTL + &CmndI2SI2SRtttl, +#endif #if defined(USE_SHINE) && defined(MP3_MIC_STREAM) - ,&Cmd_MP3Stream + &CmndI2SMP3Stream, #endif // MP3_MIC_STREAM #ifdef I2S_BRIDGE - ,&Cmd_I2SBridge + &CmndI2SI2SBridge, #endif // I2S_BRIDGE }; -void Cmd_WebRadio(void) { +void CmndI2SStop(void) { + I2sStopPlaying(); + ResponseCmndDone(); +} + +void CmndI2SWebRadio(void) { if (!audio_i2s.out) return; if (audio_i2s.decoder) { @@ -921,14 +960,33 @@ void Cmd_WebRadio(void) { } } -void Cmd_Play(void) { +void CmndI2SPlay(void) { if (XdrvMailbox.data_len > 0) { - Play_mp3(XdrvMailbox.data); + int32_t err = I2SPlayMp3(XdrvMailbox.data); + // display return message + switch (err) { + case I2S_OK: + ResponseCmndDone(); + break; + case I2S_ERR_OUTPUT_NOT_CONFIGURE: + ResponseCmndChar("I2S output not configured"); + break; + case I2S_ERR_DECODER_IN_USE: + ResponseCmndChar("Decoder already in use"); + break; + case I2S_ERR_FILE_NOT_FOUND: + ResponseCmndChar("File not found"); + break; + default: + ResponseCmndChar("Unknown error"); + break; + } + } else { + ResponseCmndChar("Missing filename"); } - ResponseCmndChar(XdrvMailbox.data); } -void Cmd_Gain(void) { +void CmndI2SGain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { if (audio_i2s.out) { audio_i2s.Settings->tx.volume = XdrvMailbox.payload; @@ -938,21 +996,21 @@ void Cmd_Gain(void) { ResponseCmndNumber(audio_i2s.Settings->tx.volume); } -void Cmd_Say(void) { +void CmndI2SSay(void) { if (XdrvMailbox.data_len > 0) { Say(XdrvMailbox.data); } ResponseCmndChar(XdrvMailbox.data); } -void Cmd_I2SRtttl(void) { +void CmndI2SI2SRtttl(void) { if (XdrvMailbox.data_len > 0) { Rtttl(XdrvMailbox.data); } ResponseCmndChar(XdrvMailbox.data); } -void Cmd_MicRec(void) { +void CmndI2SMicRec(void) { if (audio_i2s.Settings->rx.mp3_encoder == 1) { if (XdrvMailbox.data_len > 0) { if (!strncmp(XdrvMailbox.data, "-?", 2)) { @@ -983,7 +1041,7 @@ else{ } // mic gain in factor not percent -void Cmd_MicGain(void) { +void CmndI2SMicGain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 256)) { audio_i2s.Settings->rx.gain = XdrvMailbox.payload; } @@ -1042,4 +1100,4 @@ bool Xdrv42(uint32_t function) { } #endif // USE_I2S_AUDIO -#endif //ESP_IDF_VERSION_MAJOR >= 5 \ No newline at end of file +#endif //ESP_IDF_VERSION_MAJOR >= 5