From 4ed5165a1179bbed00ca4bfe654e512b892007fb Mon Sep 17 00:00:00 2001 From: raul Date: Mon, 19 Nov 2018 01:34:52 +0100 Subject: [PATCH 1/6] i2s can send now buffers --- cores/esp8266/core_esp8266_i2s.c | 39 ++++++++++++++++++++++++++++++++ cores/esp8266/i2s.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/cores/esp8266/core_esp8266_i2s.c b/cores/esp8266/core_esp8266_i2s.c index 046c6dd064..9708aaf7a2 100644 --- a/cores/esp8266/core_esp8266_i2s.c +++ b/cores/esp8266/core_esp8266_i2s.c @@ -331,6 +331,45 @@ bool i2s_write_lr(int16_t left, int16_t right){ return i2s_write_sample(sample); } +#define MIN(a,b) (acurr_slc_buf_pos==SLC_BUF_LEN || tx->curr_slc_buf==NULL) { + // no room in the current buffer? if there are no buffers available then exit + if (tx->slc_queue_len == 0) + break; + + // get a new buffer + ETS_SLC_INTR_DISABLE(); + tx->curr_slc_buf = (uint32_t *)i2s_slc_queue_next_item(tx); + ETS_SLC_INTR_ENABLE(); + tx->curr_slc_buf_pos=0; + } + + //space available in the current buffer + int16_t available = _i2s_available( tx ); + + int16_t m = MIN(available,len); + + for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v<<16) | (v & 0xffff); + sample++; + } + len -= m; + samples_written += m; + } + return samples_written; +} + bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) { if (!rx) { return false; diff --git a/cores/esp8266/i2s.h b/cores/esp8266/i2s.h index 6f1761e6fa..1b0621bf80 100644 --- a/cores/esp8266/i2s.h +++ b/cores/esp8266/i2s.h @@ -58,6 +58,8 @@ int16_t i2s_available();// returns the number of samples than can be written bef int16_t i2s_rx_available();// returns the number of samples than can be written before blocking void i2s_set_callback(void (*callback) (void)); void i2s_rx_set_callback(void (*callback) (void)); +int16_t i2s_write_buffer_mono(int16_t *sample, int16_t len); //writes a number of samplers in the the DMA mem, returns the numner of written samples + #ifdef __cplusplus } From 000dc710352a335c749588e5b97fdbb5716b2d53 Mon Sep 17 00:00:00 2001 From: raul Date: Tue, 20 Nov 2018 20:50:32 +0100 Subject: [PATCH 2/6] adding mono and stereo, with blocking and non blocking support --- cores/esp8266/core_esp8266_i2s.c | 75 ++++++++++++++++++++++---------- cores/esp8266/i2s.h | 7 ++- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/cores/esp8266/core_esp8266_i2s.c b/cores/esp8266/core_esp8266_i2s.c index 9708aaf7a2..f5d0a7bbc6 100644 --- a/cores/esp8266/core_esp8266_i2s.c +++ b/cores/esp8266/core_esp8266_i2s.c @@ -331,21 +331,34 @@ bool i2s_write_lr(int16_t left, int16_t right){ return i2s_write_sample(sample); } -#define MIN(a,b) (acurr_slc_buf_pos==SLC_BUF_LEN || tx->curr_slc_buf==NULL) { // no room in the current buffer? if there are no buffers available then exit if (tx->slc_queue_len == 0) - break; + { + if (nb) { + // if nonblocking just return the number of frames written so far + break; + } + else { + while (1) { + if (tx->slc_queue_len > 0) { + break; + } else { + optimistic_yield(10000); + } + } + } + } // get a new buffer ETS_SLC_INTR_DISABLE(); @@ -354,22 +367,40 @@ int16_t i2s_write_buffer_mono(int16_t *sample, int16_t len) { tx->curr_slc_buf_pos=0; } - //space available in the current buffer - int16_t available = _i2s_available( tx ); - - int16_t m = MIN(available,len); - - for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v<<16) | (v & 0xffff); - sample++; - } - len -= m; - samples_written += m; - } - return samples_written; + //space available in the current buffer + int16_t available = _i2s_available( tx ); + + int16_t fc = (available < frame_count) ? available : frame_count; + + if (mono) { + for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | (v & 0xffff); + } + } + else + { + for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | (v2 & 0xffff); + } + } + + len -= fc; + frames_written += fc; + } + return frames_written; } +int16_t i2s_write_buffer_mono_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); } + +int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); } + +int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); } + +int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false false); } + bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) { if (!rx) { return false; diff --git a/cores/esp8266/i2s.h b/cores/esp8266/i2s.h index 1b0621bf80..3fb2311341 100644 --- a/cores/esp8266/i2s.h +++ b/cores/esp8266/i2s.h @@ -58,8 +58,13 @@ int16_t i2s_available();// returns the number of samples than can be written bef int16_t i2s_rx_available();// returns the number of samples than can be written before blocking void i2s_set_callback(void (*callback) (void)); void i2s_rx_set_callback(void (*callback) (void)); -int16_t i2s_write_buffer_mono(int16_t *sample, int16_t len); //writes a number of samplers in the the DMA mem, returns the numner of written samples +// writes a buffer of frames into the DMA memory, returns the amount of frames written +// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel. +int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count); +int16_t i2s_write_buffer_mono_nb(int16_t *frames, int16_t frame_count); +int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count); +int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count); #ifdef __cplusplus } From f2aa60563a6ba617e03ce165fa28a118ee459078 Mon Sep 17 00:00:00 2001 From: raul Date: Tue, 20 Nov 2018 22:41:38 +0100 Subject: [PATCH 3/6] fixing crash --- cores/esp8266/core_esp8266_i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/core_esp8266_i2s.c b/cores/esp8266/core_esp8266_i2s.c index f5d0a7bbc6..18d9c88718 100644 --- a/cores/esp8266/core_esp8266_i2s.c +++ b/cores/esp8266/core_esp8266_i2s.c @@ -387,7 +387,7 @@ int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono, bool } } - len -= fc; + frame_count -= fc; frames_written += fc; } return frames_written; @@ -399,7 +399,7 @@ int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count) { return _i2 int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); } -int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false false); } +int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); } bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) { if (!rx) { From 1abc8491bc34dcb3c1f621b42e270e1f39882f08 Mon Sep 17 00:00:00 2001 From: raul Date: Wed, 21 Nov 2018 23:20:04 +0100 Subject: [PATCH 4/6] cosmetic changes --- cores/esp8266/core_esp8266_i2s.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/cores/esp8266/core_esp8266_i2s.c b/cores/esp8266/core_esp8266_i2s.c index 18d9c88718..abb4364fa6 100644 --- a/cores/esp8266/core_esp8266_i2s.c +++ b/cores/esp8266/core_esp8266_i2s.c @@ -333,13 +333,11 @@ bool i2s_write_lr(int16_t left, int16_t right){ // writes a buffer of frames into the DMA memory, returns the amount of frames written // A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel. -int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono, bool nb) { +static int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono, bool nb) { int16_t frames_written=0; - for(;;) { - if (frame_count==0) - break; - + while(frame_count>0) { + // make sure we have room in the current buffer if (tx->curr_slc_buf_pos==SLC_BUF_LEN || tx->curr_slc_buf==NULL) { // no room in the current buffer? if there are no buffers available then exit @@ -368,24 +366,25 @@ int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono, bool } //space available in the current buffer - int16_t available = _i2s_available( tx ); + int16_t available = SLC_BUF_LEN - tx->curr_slc_buf_pos; int16_t fc = (available < frame_count) ? available : frame_count; if (mono) { for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | (v & 0xffff); - } + uint16_t v = (uint16_t)(*frames); + tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | (v & 0xffff);; + frames++; + } } else { for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | (v2 & 0xffff); } - } + } frame_count -= fc; frames_written += fc; From 48b07abd90030b9425a9d86a47a43906ec21c351 Mon Sep 17 00:00:00 2001 From: raul Date: Fri, 23 Nov 2018 20:47:19 +0100 Subject: [PATCH 5/6] we dont need the & 0xffff --- cores/esp8266/core_esp8266_i2s.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/core_esp8266_i2s.c b/cores/esp8266/core_esp8266_i2s.c index abb4364fa6..89ee21cd9d 100644 --- a/cores/esp8266/core_esp8266_i2s.c +++ b/cores/esp8266/core_esp8266_i2s.c @@ -372,17 +372,16 @@ static int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono if (mono) { for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | (v & 0xffff);; - frames++; + uint16_t v = (uint16_t)(*frames++); + tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | v; } } else { for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | (v2 & 0xffff); + tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | v2; } } From 862411723dd8b9fbb9a5a89747c02a1de1a1d0a8 Mon Sep 17 00:00:00 2001 From: raul Date: Sat, 24 Nov 2018 01:21:43 +0100 Subject: [PATCH 6/6] using unsigned integers since we'll never be using negative numbers --- cores/esp8266/core_esp8266_i2s.c | 30 +++++++++++++++--------------- cores/esp8266/i2s.h | 12 ++++++------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cores/esp8266/core_esp8266_i2s.c b/cores/esp8266/core_esp8266_i2s.c index 89ee21cd9d..7c8b4b73ac 100644 --- a/cores/esp8266/core_esp8266_i2s.c +++ b/cores/esp8266/core_esp8266_i2s.c @@ -113,18 +113,18 @@ bool i2s_rx_is_empty() { return _i2s_is_empty( rx ); } -static int16_t _i2s_available(const i2s_state_t *ch) { +static uint16_t _i2s_available(const i2s_state_t *ch) { if (!ch) { return 0; } return (SLC_BUF_CNT - ch->slc_queue_len) * SLC_BUF_LEN; } -int16_t i2s_available(){ +uint16_t i2s_available(){ return _i2s_available( tx ); } -int16_t i2s_rx_available(){ +uint16_t i2s_rx_available(){ return _i2s_available( rx ); } @@ -333,8 +333,8 @@ bool i2s_write_lr(int16_t left, int16_t right){ // writes a buffer of frames into the DMA memory, returns the amount of frames written // A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel. -static int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono, bool nb) { - int16_t frames_written=0; +static uint16_t _i2s_write_buffer(int16_t *frames, uint16_t frame_count, bool mono, bool nb) { + uint16_t frames_written=0; while(frame_count>0) { @@ -366,21 +366,21 @@ static int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono } //space available in the current buffer - int16_t available = SLC_BUF_LEN - tx->curr_slc_buf_pos; + uint16_t available = SLC_BUF_LEN - tx->curr_slc_buf_pos; - int16_t fc = (available < frame_count) ? available : frame_count; + uint16_t fc = (available < frame_count) ? available : frame_count; if (mono) { - for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | v; } } else { - for(int16_t i=0;icurr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | v2; } } @@ -391,13 +391,13 @@ static int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono return frames_written; } -int16_t i2s_write_buffer_mono_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); } +uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); } -int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); } +uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); } -int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); } +uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); } -int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); } +uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); } bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) { if (!rx) { diff --git a/cores/esp8266/i2s.h b/cores/esp8266/i2s.h index 3fb2311341..70587fd2fb 100644 --- a/cores/esp8266/i2s.h +++ b/cores/esp8266/i2s.h @@ -54,17 +54,17 @@ bool i2s_is_full();//returns true if DMA is full and can not take more bytes (ov bool i2s_is_empty();//returns true if DMA is empty (underflow) bool i2s_rx_is_full(); bool i2s_rx_is_empty(); -int16_t i2s_available();// returns the number of samples than can be written before blocking -int16_t i2s_rx_available();// returns the number of samples than can be written before blocking +uint16_t i2s_available();// returns the number of samples than can be written before blocking +uint16_t i2s_rx_available();// returns the number of samples than can be written before blocking void i2s_set_callback(void (*callback) (void)); void i2s_rx_set_callback(void (*callback) (void)); // writes a buffer of frames into the DMA memory, returns the amount of frames written // A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel. -int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count); -int16_t i2s_write_buffer_mono_nb(int16_t *frames, int16_t frame_count); -int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count); -int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count); +uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count); +uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count); +uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count); +uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count); #ifdef __cplusplus }