mirror of https://github.com/arendst/Tasmota.git
final i2s fix (#21770)
This commit is contained in:
parent
7e22861090
commit
3d34097275
|
@ -105,7 +105,7 @@ public:
|
||||||
|
|
||||||
void setSlotConfig(i2s_port_t i2s_port, uint8_t tx_slot_config,
|
void setSlotConfig(i2s_port_t i2s_port, uint8_t tx_slot_config,
|
||||||
uint8_t tx_slot_mask, uint8_t rx_slot_mask) {
|
uint8_t tx_slot_mask, uint8_t rx_slot_mask) {
|
||||||
_i2s_port = i2s_port;
|
// _i2s_port = i2s_port;
|
||||||
_tx_slot_config = tx_slot_config;
|
_tx_slot_config = tx_slot_config;
|
||||||
}
|
}
|
||||||
void setRxFreq(uint16_t freq) { _rx_freq = freq; }
|
void setRxFreq(uint16_t freq) { _rx_freq = freq; }
|
||||||
|
@ -323,14 +323,9 @@ bool TasmotaI2S::beginTx(void) {
|
||||||
} else
|
} else
|
||||||
#endif // SOC_DAC_SUPPORTED
|
#endif // SOC_DAC_SUPPORTED
|
||||||
{
|
{
|
||||||
uint8_t zero_buffer[240] = {0};
|
|
||||||
size_t sz;
|
|
||||||
for(int i = 0;i < 6;i++){
|
|
||||||
i2s_channel_preload_data(_tx_handle, zero_buffer, sizeof(zero_buffer), &sz); // preload DMA buffer with silence
|
|
||||||
}
|
|
||||||
err = i2s_channel_enable(_tx_handle);
|
err = i2s_channel_enable(_tx_handle);
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_INFO, "I2S: Tx i2s_channel_enable err=0x%04X", err);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: Tx i2s_channel_enable err=0x%04X", err);
|
||||||
if (err != ERR_OK){
|
if (err != ERR_OK){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -349,6 +344,11 @@ bool TasmotaI2S::stopTx() {
|
||||||
dac_task_stop();
|
dac_task_stop();
|
||||||
err = dac_continuous_disable((dac_continuous_handle_t) _tx_handle);
|
err = dac_continuous_disable((dac_continuous_handle_t) _tx_handle);
|
||||||
} else {
|
} else {
|
||||||
|
uint8_t zero_buffer[240] = {0};
|
||||||
|
size_t sz;
|
||||||
|
for(int i = 0;i < 6;i++){
|
||||||
|
i2s_channel_write(_tx_handle, zero_buffer, sizeof(zero_buffer), &sz, 0); // fill DMA buffer with silence
|
||||||
|
}
|
||||||
err = i2s_channel_disable(_tx_handle);
|
err = i2s_channel_disable(_tx_handle);
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_DEBUG, "I2S: stopTx i2s_channel_disable err=0x%04X", err);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: stopTx i2s_channel_disable err=0x%04X", err);
|
||||||
|
@ -364,7 +364,7 @@ bool TasmotaI2S::stopTx() {
|
||||||
AddLog(LOG_LEVEL_DEBUG, "I2S: stopTx i2s_del_channel err=0x%04X", err);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: stopTx i2s_del_channel err=0x%04X", err);
|
||||||
_tx_handle = nullptr;
|
_tx_handle = nullptr;
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_INFO, "I2S: stop: I2S channel disabled");
|
AddLog(LOG_LEVEL_DEBUG, "I2S: stop: I2S channel disabled");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ void TasmotaI2S::flush()
|
||||||
delay(1);
|
delay(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_INFO, "I2S: flush DMA TX buffer");
|
AddLog(LOG_LEVEL_DEBUG, "I2S: flush DMA TX buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaI2S::delTxHandle(void) {
|
bool TasmotaI2S::delTxHandle(void) {
|
||||||
|
|
|
@ -718,8 +718,8 @@ void I2sInit(void) {
|
||||||
audio_i2s.Settings->tx.slot_mask, audio_i2s.Settings->rx.slot_mask);
|
audio_i2s.Settings->tx.slot_mask, audio_i2s.Settings->rx.slot_mask);
|
||||||
if (tx) {
|
if (tx) {
|
||||||
i2s->setTxMode(audio_i2s.Settings->tx.mode);
|
i2s->setTxMode(audio_i2s.Settings->tx.mode);
|
||||||
i2s->setTxChannels(audio_i2s.Settings->tx.channels);
|
// i2s->setTxChannels(audio_i2s.Settings->tx.channels);
|
||||||
i2s->setRate(audio_i2s.Settings->tx.sample_rate);
|
// i2s->setRate(audio_i2s.Settings->tx.sample_rate);
|
||||||
}
|
}
|
||||||
if (rx) {
|
if (rx) {
|
||||||
i2s->setRxMode(audio_i2s.Settings->rx.mode);
|
i2s->setRxMode(audio_i2s.Settings->rx.mode);
|
||||||
|
@ -786,20 +786,7 @@ void I2sInit(void) {
|
||||||
//
|
//
|
||||||
// Returns `I2S_OK` if ok to send to output or error code
|
// Returns `I2S_OK` if ok to send to output or error code
|
||||||
int32_t I2SPrepareTx(void) {
|
int32_t I2SPrepareTx(void) {
|
||||||
|
I2sStopPlaying();
|
||||||
if(audio_i2s_mp3.task_running){
|
|
||||||
audio_i2s_mp3.task_running = false;
|
|
||||||
while(!audio_i2s_mp3.task_has_ended){
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio_i2s_mp3.mic_task_handle) {
|
|
||||||
audio_i2s_mp3.mic_stop = 1;
|
|
||||||
while (audio_i2s_mp3.mic_stop) {
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddLog(LOG_LEVEL_DEBUG, "I2S: I2SPrepareTx out=%p", audio_i2s.out);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: I2SPrepareTx out=%p", audio_i2s.out);
|
||||||
if (!audio_i2s.out) { return I2S_ERR_OUTPUT_NOT_CONFIGURED; }
|
if (!audio_i2s.out) { return I2S_ERR_OUTPUT_NOT_CONFIGURED; }
|
||||||
|
@ -835,13 +822,12 @@ void I2sMp3Task(void *arg) {
|
||||||
audio_i2s_mp3.task_running = true;
|
audio_i2s_mp3.task_running = true;
|
||||||
while (audio_i2s_mp3.mp3->isRunning() && audio_i2s_mp3.task_running) {
|
while (audio_i2s_mp3.mp3->isRunning() && audio_i2s_mp3.task_running) {
|
||||||
if (!audio_i2s_mp3.mp3->loop()) {
|
if (!audio_i2s_mp3.mp3->loop()) {
|
||||||
audio_i2s_mp3.task_running == false;
|
audio_i2s_mp3.task_running = false;
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
}
|
}
|
||||||
audio_i2s.out->flush();
|
audio_i2s.out->flush();
|
||||||
audio_i2s_mp3.mp3->stop();
|
audio_i2s_mp3.mp3->stop();
|
||||||
I2sStopPlaying();
|
|
||||||
mp3_delete();
|
mp3_delete();
|
||||||
audio_i2s_mp3.mp3_task_handle = nullptr;
|
audio_i2s_mp3.mp3_task_handle = nullptr;
|
||||||
audio_i2s_mp3.task_has_ended = true;
|
audio_i2s_mp3.task_has_ended = true;
|
||||||
|
@ -853,8 +839,7 @@ void I2sStatusCallback(void *cbData, int code, const char *string) {
|
||||||
const char *ptr = reinterpret_cast<const char *>(cbData);
|
const char *ptr = reinterpret_cast<const char *>(cbData);
|
||||||
(void) code;
|
(void) code;
|
||||||
(void) ptr;
|
(void) ptr;
|
||||||
//strncpy_P(status, string, sizeof(status)-1);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: -> %s", string);
|
||||||
//status[sizeof(status)-1] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
|
@ -870,7 +855,7 @@ void I2sMp3WrTask(void *arg){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
audio_i2s.out->flush();
|
audio_i2s.out->flush();
|
||||||
I2sStopPlaying();
|
I2sWebRadioStopPlaying();
|
||||||
audio_i2s_mp3.mp3_task_handle = nullptr;
|
audio_i2s_mp3.mp3_task_handle = nullptr;
|
||||||
audio_i2s_mp3.task_has_ended = true;
|
audio_i2s_mp3.task_has_ended = true;
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
@ -879,11 +864,23 @@ void I2sMp3WrTask(void *arg){
|
||||||
#endif // USE_I2S_MP3
|
#endif // USE_I2S_MP3
|
||||||
|
|
||||||
void I2sStopPlaying() {
|
void I2sStopPlaying() {
|
||||||
|
|
||||||
#ifdef USE_I2S_WEBRADIO
|
|
||||||
I2sWebRadioStopPlaying();
|
|
||||||
#endif
|
|
||||||
I2SAudioPower(false);
|
I2SAudioPower(false);
|
||||||
|
|
||||||
|
if(audio_i2s_mp3.task_running){
|
||||||
|
audio_i2s_mp3.task_running = false;
|
||||||
|
while(audio_i2s_mp3.task_has_ended == false){
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
while(audio_i2s_mp3.mp3){
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (audio_i2s_mp3.mic_task_handle) {
|
||||||
|
audio_i2s_mp3.mic_stop = 1;
|
||||||
|
while (audio_i2s_mp3.mic_stop) {
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
|
@ -891,9 +888,9 @@ void I2sStopPlaying() {
|
||||||
//
|
//
|
||||||
// Returns I2S_error_t
|
// Returns I2S_error_t
|
||||||
int32_t I2SPlayMp3(const char *path) {
|
int32_t I2SPlayMp3(const char *path) {
|
||||||
int32_t i2s_err = I2S_OK;
|
int32_t i2s_err = I2SPrepareTx();
|
||||||
if ((i2s_err = I2SPrepareTx()) != I2S_OK) { return i2s_err; }
|
if ((i2s_err) != I2S_OK) { return i2s_err; }
|
||||||
if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return I2S_ERR_DECODER_IN_USE;
|
if (audio_i2s_mp3.mp3) return I2S_ERR_DECODER_IN_USE;
|
||||||
|
|
||||||
// check if the filename starts with '/', if not add it
|
// check if the filename starts with '/', if not add it
|
||||||
char fname[64];
|
char fname[64];
|
||||||
|
@ -926,13 +923,14 @@ void mp3_delete(void) {
|
||||||
delete audio_i2s_mp3.file;
|
delete audio_i2s_mp3.file;
|
||||||
delete audio_i2s_mp3.id3;
|
delete audio_i2s_mp3.id3;
|
||||||
delete audio_i2s_mp3.mp3;
|
delete audio_i2s_mp3.mp3;
|
||||||
audio_i2s_mp3.mp3=nullptr;
|
audio_i2s_mp3.mp3 = nullptr;
|
||||||
|
|
||||||
if (audio_i2s_mp3.decoder) {
|
// if (audio_i2s_mp3.decoder) {
|
||||||
audio_i2s_mp3.decoder->stop();
|
// audio_i2s_mp3.decoder->stop();
|
||||||
delete audio_i2s_mp3.decoder;
|
// delete audio_i2s_mp3.decoder;
|
||||||
audio_i2s_mp3.decoder = NULL;
|
// audio_i2s_mp3.decoder = nullptr;
|
||||||
}
|
// AddLog(LOG_LEVEL_DEBUG, "I2S: audio_i2s_mp3.decoder = nullptr");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
#endif // USE_I2S_MP3
|
#endif // USE_I2S_MP3
|
||||||
|
|
||||||
|
@ -974,16 +972,12 @@ void CmndI2SStop(void) {
|
||||||
ResponseCmndChar("I2S output not configured");
|
ResponseCmndChar("I2S output not configured");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
I2sStopPlaying();
|
audio_i2s.out->setGain(0);
|
||||||
ResponseCmndDone();
|
ResponseCmndDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
void CmndI2SPlay(void) {
|
void CmndI2SPlay(void) {
|
||||||
if (I2SPrepareTx()) {
|
|
||||||
ResponseCmndChar("I2S output not configured");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
int32_t err = I2SPlayMp3(XdrvMailbox.data);
|
int32_t err = I2SPlayMp3(XdrvMailbox.data);
|
||||||
// display return message
|
// display return message
|
||||||
|
|
|
@ -75,11 +75,18 @@ void Webradio(const char *url) {
|
||||||
I2sWebRadioStopPlaying();
|
I2sWebRadioStopPlaying();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
AddLog(LOG_LEVEL_INFO, "I2S: did connect to %s",url);
|
||||||
|
|
||||||
I2SAudioPower(true);
|
I2SAudioPower(true);
|
||||||
Audio_webradio.buff = new AudioFileSourceBuffer(Audio_webradio.ifile, Audio_webradio.preallocateBuffer, preallocateBufferSize);
|
Audio_webradio.buff = new AudioFileSourceBuffer(Audio_webradio.ifile, Audio_webradio.preallocateBuffer, preallocateBufferSize);
|
||||||
|
if(Audio_webradio.buff == nullptr){
|
||||||
|
return;
|
||||||
|
}
|
||||||
Audio_webradio.buff->RegisterStatusCB(I2sStatusCallback, NULL);
|
Audio_webradio.buff->RegisterStatusCB(I2sStatusCallback, NULL);
|
||||||
audio_i2s_mp3.decoder = new AudioGeneratorMP3(Audio_webradio.preallocateCodec, preallocateCodecSize);
|
audio_i2s_mp3.decoder = new AudioGeneratorMP3(Audio_webradio.preallocateCodec, preallocateCodecSize);
|
||||||
|
if(audio_i2s_mp3.decoder == nullptr){
|
||||||
|
return;
|
||||||
|
}
|
||||||
audio_i2s_mp3.decoder->RegisterStatusCB(I2sStatusCallback, NULL);
|
audio_i2s_mp3.decoder->RegisterStatusCB(I2sStatusCallback, NULL);
|
||||||
audio_i2s_mp3.decoder->begin(Audio_webradio.buff, audio_i2s.out);
|
audio_i2s_mp3.decoder->begin(Audio_webradio.buff, audio_i2s.out);
|
||||||
if (!audio_i2s_mp3.decoder->isRunning()) {
|
if (!audio_i2s_mp3.decoder->isRunning()) {
|
||||||
|
|
Loading…
Reference in New Issue