2727#include "i2s_reg.h"
2828#include "i2s.h"
2929
30- extern void ets_wdt_enable (void );
31- extern void ets_wdt_disable (void );
30+ // IOs used for I2S. Not defined in i2s.h, unfortunately.
31+ // Note these are internal IOs numbers and not pins on an
32+ // Arduino board. Users need to verify their particular wiring.
33+ #define I2SO_WS 2
34+ #define I2SO_DATA 3
35+ #define I2SO_BCK 15
3236
3337#define SLC_BUF_CNT (8) //Number of buffers in the I2S circular buffer
3438#define SLC_BUF_LEN (64) //Length of one buffer, in 32-bit words.
@@ -56,21 +60,21 @@ static uint32_t *i2s_slc_buf_pntr[SLC_BUF_CNT]; //Pointer to the I2S DMA buffer
5660static struct slc_queue_item i2s_slc_items [SLC_BUF_CNT ]; //I2S DMA buffer descriptors
5761static uint32_t * i2s_curr_slc_buf = NULL ;//current buffer for writing
5862static int i2s_curr_slc_buf_pos = 0 ; //position in the current buffer
59- static void (* i2s_callback ) (void )= 0 ; //Callback function should be defined as 'void ICACHE_FLASH_ATTR function_name()', placing the function in IRAM for faster execution. Avoid long computational tasks in this function, use it to set flags and process later.
63+ static void (* i2s_callback ) (void )= 0 ; //Callback function should be defined as 'void ICACHE_RAM_ATTR function_name()', placing the function in IRAM for faster execution. Avoid long computational tasks in this function, use it to set flags and process later.
6064
61- bool ICACHE_FLASH_ATTR i2s_is_full (){
65+ bool i2s_is_full (){
6266 return (i2s_curr_slc_buf_pos == SLC_BUF_LEN || i2s_curr_slc_buf == NULL ) && (i2s_slc_queue_len == 0 );
6367}
6468
65- bool ICACHE_FLASH_ATTR i2s_is_empty (){
69+ bool i2s_is_empty (){
6670 return (i2s_slc_queue_len >= SLC_BUF_CNT - 1 );
6771}
6872
69- int16_t ICACHE_FLASH_ATTR i2s_available (){
70- return (SLC_BUF_CNT - i2s_slc_queue_len ) * SLC_BUF_LEN ;
73+ int16_t i2s_available (){
74+ return (SLC_BUF_CNT - i2s_slc_queue_len ) * SLC_BUF_LEN ;
7175}
7276
73- uint32_t ICACHE_FLASH_ATTR i2s_slc_queue_next_item (){ //pop the top off the queue
77+ uint32_t ICACHE_RAM_ATTR i2s_slc_queue_next_item (){ //pop the top off the queue
7478 uint8_t i ;
7579 uint32_t item = i2s_slc_queue [0 ];
7680 i2s_slc_queue_len -- ;
@@ -82,13 +86,13 @@ uint32_t ICACHE_FLASH_ATTR i2s_slc_queue_next_item(){ //pop the top off the queu
8286//This routine is called as soon as the DMA routine has something to tell us. All we
8387//handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
8488//descriptor has the 'EOF' field set to 1.
85- void ICACHE_FLASH_ATTR i2s_slc_isr (void ) {
89+ void ICACHE_RAM_ATTR i2s_slc_isr (void ) {
8690 uint32_t slc_intr_status = SLCIS ;
8791 SLCIC = 0xFFFFFFFF ;
8892 if (slc_intr_status & SLCIRXEOF ) {
8993 ETS_SLC_INTR_DISABLE ();
9094 struct slc_queue_item * finished_item = (struct slc_queue_item * )SLCRXEDA ;
91- memset ((void * )finished_item -> buf_ptr , 0x00 , SLC_BUF_LEN * 4 );//zero the buffer so it is mute in case of underflow
95+ ets_memset ((void * )finished_item -> buf_ptr , 0x00 , SLC_BUF_LEN * 4 );//zero the buffer so it is mute in case of underflow
9296 if (i2s_slc_queue_len >= SLC_BUF_CNT - 1 ) { //All buffers are empty. This means we have an underflow
9397 i2s_slc_queue_next_item (); //free space for finished_item
9498 }
@@ -102,7 +106,7 @@ void i2s_set_callback(void (*callback) (void)){
102106 i2s_callback = callback ;
103107}
104108
105- void ICACHE_FLASH_ATTR i2s_slc_begin (){
109+ void i2s_slc_begin (){
106110 i2s_slc_queue_len = 0 ;
107111 int x , y ;
108112
@@ -150,7 +154,7 @@ void ICACHE_FLASH_ATTR i2s_slc_begin(){
150154 SLCRXL |= SLCRXLS ;
151155}
152156
153- void ICACHE_FLASH_ATTR i2s_slc_end (){
157+ void i2s_slc_end (){
154158 ETS_SLC_INTR_DISABLE ();
155159 SLCIC = 0xFFFFFFFF ;
156160 SLCIE = 0 ;
@@ -166,15 +170,14 @@ void ICACHE_FLASH_ATTR i2s_slc_end(){
166170//at least the current sample rate. You can also call it quicker: it will suspend the calling
167171//thread if the buffer is full and resume when there's room again.
168172
169- bool ICACHE_FLASH_ATTR i2s_write_sample (uint32_t sample ) {
173+ bool i2s_write_sample (uint32_t sample ) {
170174 if (i2s_curr_slc_buf_pos == SLC_BUF_LEN || i2s_curr_slc_buf == NULL ) {
171175 if (i2s_slc_queue_len == 0 ){
172176 while (1 ){
173177 if (i2s_slc_queue_len > 0 ){
174178 break ;
175179 } else {
176- ets_wdt_disable ();
177- ets_wdt_enable ();
180+ optimistic_yield (10000 );
178181 }
179182 }
180183 }
@@ -187,7 +190,7 @@ bool ICACHE_FLASH_ATTR i2s_write_sample(uint32_t sample) {
187190 return true;
188191}
189192
190- bool ICACHE_FLASH_ATTR i2s_write_sample_nb (uint32_t sample ) {
193+ bool i2s_write_sample_nb (uint32_t sample ) {
191194 if (i2s_curr_slc_buf_pos == SLC_BUF_LEN || i2s_curr_slc_buf == NULL ) {
192195 if (i2s_slc_queue_len == 0 ){
193196 return false;
@@ -201,7 +204,7 @@ bool ICACHE_FLASH_ATTR i2s_write_sample_nb(uint32_t sample) {
201204 return true;
202205}
203206
204- bool ICACHE_FLASH_ATTR i2s_write_lr (int16_t left , int16_t right ){
207+ bool i2s_write_lr (int16_t left , int16_t right ){
205208 int sample = right & 0xFFFF ;
206209 sample = sample << 16 ;
207210 sample |= left & 0xFFFF ;
@@ -215,7 +218,7 @@ bool ICACHE_FLASH_ATTR i2s_write_lr(int16_t left, int16_t right){
215218
216219static uint32_t _i2s_sample_rate ;
217220
218- void ICACHE_FLASH_ATTR i2s_set_rate (uint32_t rate ){ //Rate in HZ
221+ void i2s_set_rate (uint32_t rate ){ //Rate in HZ
219222 if (rate == _i2s_sample_rate ) return ;
220223 _i2s_sample_rate = rate ;
221224
@@ -235,60 +238,68 @@ void ICACHE_FLASH_ATTR i2s_set_rate(uint32_t rate){ //Rate in HZ
235238 }
236239 }
237240
238- //os_printf("Rate %u Div %u Bck %u Frq %u\n", _i2s_sample_rate, i2s_clock_div, i2s_bck_div, I2SBASEFREQ/(i2s_clock_div*i2s_bck_div*2));
239-
240- //!trans master, !bits mod, rece slave mod, rece msb shift, right first, msb right
241- I2SC &= ~(I2STSM | (I2SBMM << I2SBM ) | (I2SBDM << I2SBD ) | (I2SCDM << I2SCD ));
242- I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | ((sbd_div_best ) << I2SBD ) | ((scd_div_best ) << I2SCD );
241+ i2s_set_dividers ( sbd_div_best , scd_div_best );
243242}
244243
245- void ICACHE_FLASH_ATTR i2s_set_dividers (uint8_t div1 , uint8_t div2 ){
244+ void i2s_set_dividers (uint8_t div1 , uint8_t div2 ) {
245+ // Ensure dividers fit in bit fields
246246 div1 &= I2SBDM ;
247247 div2 &= I2SCDM ;
248248
249+ // !trans master(?), !bits mod(==16 bits/chanel), clear clock dividers
249250 I2SC &= ~(I2STSM | (I2SBMM << I2SBM ) | (I2SBDM << I2SBD ) | (I2SCDM << I2SCD ));
250- I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | (div1 << I2SBD ) | (div2 << I2SCD );
251+
252+ // I2SRF = Send/recv right channel first (? may be swapped form I2S spec of WS=0 => left)
253+ // I2SMR = MSB recv/xmit first
254+ // I2SRSM = Receive slave mode (?)
255+ // I2SRMS, I2STMS = 1-bit delay from WS to MSB (I2S format)
256+ // div1, div2 = Set I2S WS clock frequency. BCLK seems to be generated from 32x this
257+ I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | I2STMS | (div1 << I2SBD ) | (div2 << I2SCD );
251258}
252259
253- float ICACHE_FLASH_ATTR i2s_get_real_rate (){
260+ float i2s_get_real_rate (){
254261 return (float )I2SBASEFREQ /32 /((I2SC >>I2SBD ) & I2SBDM )/((I2SC >> I2SCD ) & I2SCDM );
255262}
256263
257- void ICACHE_FLASH_ATTR i2s_begin (){
264+ void i2s_begin () {
258265 _i2s_sample_rate = 0 ;
259266 i2s_slc_begin ();
260-
261- pinMode (2 , FUNCTION_1 ); //I2SO_WS (LRCK)
262- pinMode (3 , FUNCTION_1 ); //I2SO_DATA (SDIN)
263- pinMode (15 , FUNCTION_1 ); //I2SO_BCK (SCLK)
267+
268+ // Redirect control of IOs to the I2S block
269+ pinMode (I2SO_WS , FUNCTION_1 );
270+ pinMode (I2SO_DATA , FUNCTION_1 );
271+ pinMode (I2SO_BCK , FUNCTION_1 );
264272
265273 I2S_CLK_ENABLE ();
266274 I2SIC = 0x3F ;
267275 I2SIE = 0 ;
268276
269- //Reset I2S
277+ // Reset I2S
270278 I2SC &= ~(I2SRST );
271279 I2SC |= I2SRST ;
272280 I2SC &= ~(I2SRST );
273-
274- I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM ) | (I2SRXFMM << I2SRXFM )); //Set RX/TX FIFO_MOD=0 and disable DMA (FIFO only)
281+
282+ // I2STXFMM, I2SRXFMM=0 => 16-bit, dual channel data shifted in/out
283+ I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM ) | (I2SRXFMM << I2SRXFM )); //Set RX/TX FIFO_MOD=0 (16-bit) and disable DMA (FIFO only)
275284 I2SFC |= I2SDE ; //Enable DMA
285+ // I2STXCMM, I2SRXCMM=0 => Dual channel mode
276286 I2SCC &= ~((I2STXCMM << I2STXCM ) | (I2SRXCMM << I2SRXCM )); //Set RX/TX CHAN_MOD=0
277287 i2s_set_rate (44100 );
278288 I2SC |= I2STXS ; //Start transmission
279289}
280290
281- void ICACHE_FLASH_ATTR i2s_end (){
291+ void i2s_end (){
282292 I2SC &= ~I2STXS ;
283293
284294 //Reset I2S
285295 I2SC &= ~(I2SRST );
286296 I2SC |= I2SRST ;
287297 I2SC &= ~(I2SRST );
288298
289- pinMode (2 , INPUT );
290- pinMode (3 , INPUT );
291- pinMode (15 , INPUT );
299+ // Redirect IOs to user control/GPIO
300+ pinMode (I2SO_WS , INPUT );
301+ pinMode (I2SO_DATA , INPUT );
302+ pinMode (I2SO_BCK , INPUT );
292303
293304 i2s_slc_end ();
294305}
0 commit comments