@@ -65,7 +65,7 @@ typedef struct i2s_state {
65
65
uint32_t * curr_slc_buf ; // Current buffer for writing
66
66
uint32_t curr_slc_buf_pos ; // Position in the current buffer
67
67
void (* callback ) (void );
68
- // Callback function should be defined as 'void ICACHE_FLASH_ATTR function_name()',
68
+ // Callback function should be defined as 'void ICACHE_RAM_ATTR function_name()',
69
69
// and be placed in IRAM for faster execution. Avoid long computational tasks in this
70
70
// function, use it to set flags and process later.
71
71
} i2s_state_t ;
@@ -74,65 +74,65 @@ typedef struct i2s_state {
74
74
static i2s_state_t * rx = NULL ;
75
75
static i2s_state_t * tx = NULL ;
76
76
77
- volatile int rx_irqs = 0 ;
78
- volatile int tx_irqs = 0 ;
77
+ volatile uint32_t rx_irqs = 0 ;
78
+ volatile uint32_t tx_irqs = 0 ;
79
79
80
80
// Some constants that aren't defined in i2s_regs.h
81
+ #define I2SO_DATA 3
82
+ #define I2SO_BCK 15
83
+ #define I2SO_WS 2
81
84
#define I2SI_DATA 12
82
85
#define I2SI_BCK 13
83
86
#define I2SI_WS 14
84
87
85
88
86
- static bool ICACHE_FLASH_ATTR _i2s_is_full (const i2s_state_t * ch ) {
89
+ static bool _i2s_is_full (const i2s_state_t * ch ) {
87
90
if (!ch ) {
88
91
return false;
89
- } else {
90
- return (ch -> curr_slc_buf_pos == SLC_BUF_LEN || ch -> curr_slc_buf == NULL ) && (ch -> slc_queue_len == 0 );
91
92
}
93
+ return (ch -> curr_slc_buf_pos == SLC_BUF_LEN || ch -> curr_slc_buf == NULL ) && (ch -> slc_queue_len == 0 );
92
94
}
93
95
94
- bool ICACHE_FLASH_ATTR i2s_is_full () {
96
+ bool i2s_is_full () {
95
97
return _i2s_is_full ( tx );
96
98
}
97
99
98
- bool ICACHE_FLASH_ATTR i2s_rx_is_full () {
100
+ bool i2s_rx_is_full () {
99
101
return _i2s_is_full ( rx );
100
102
}
101
103
102
- static bool ICACHE_FLASH_ATTR _i2s_is_empty (const i2s_state_t * ch ) {
104
+ static bool _i2s_is_empty (const i2s_state_t * ch ) {
103
105
if (!ch ) {
104
106
return false;
105
- } else {
106
- return (ch -> slc_queue_len >= SLC_BUF_CNT - 1 );
107
107
}
108
+ return (ch -> slc_queue_len >= SLC_BUF_CNT - 1 );
108
109
}
109
110
110
- bool ICACHE_FLASH_ATTR i2s_is_empty () {
111
+ bool i2s_is_empty () {
111
112
return _i2s_is_empty ( tx );
112
113
}
113
114
114
- bool ICACHE_FLASH_ATTR i2s_rx_is_empty () {
115
+ bool i2s_rx_is_empty () {
115
116
return _i2s_is_empty ( rx );
116
117
}
117
118
118
- static int16_t ICACHE_FLASH_ATTR _i2s_available (const i2s_state_t * ch ) {
119
+ static int16_t _i2s_available (const i2s_state_t * ch ) {
119
120
if (!ch ) {
120
121
return 0 ;
121
- } else {
122
- return (SLC_BUF_CNT - ch -> slc_queue_len ) * SLC_BUF_LEN ;
123
122
}
123
+ return (SLC_BUF_CNT - ch -> slc_queue_len ) * SLC_BUF_LEN ;
124
124
}
125
125
126
- int16_t ICACHE_FLASH_ATTR i2s_available (){
126
+ int16_t i2s_available (){
127
127
return _i2s_available ( tx );
128
128
}
129
129
130
- int16_t ICACHE_FLASH_ATTR i2s_rx_available (){
130
+ int16_t i2s_rx_available (){
131
131
return _i2s_available ( rx );
132
132
}
133
133
134
134
// Pop the top off of the queue and return it
135
- uint32_t * ICACHE_FLASH_ATTR i2s_slc_queue_next_item (i2s_state_t * ch ) {
135
+ static uint32_t * ICACHE_RAM_ATTR i2s_slc_queue_next_item (i2s_state_t * ch ) {
136
136
uint8_t i ;
137
137
uint32_t * item = ch -> slc_queue [0 ];
138
138
ch -> slc_queue_len -- ;
@@ -143,7 +143,7 @@ uint32_t * ICACHE_FLASH_ATTR i2s_slc_queue_next_item(i2s_state_t *ch) {
143
143
}
144
144
145
145
// Append an item to the end of the queue from receive
146
- void ICACHE_FLASH_ATTR i2s_slc_queue_append_item (i2s_state_t * ch , uint32_t * item ) {
146
+ static void ICACHE_RAM_ATTR i2s_slc_queue_append_item (i2s_state_t * ch , uint32_t * item ) {
147
147
// Shift everything up, except for the one corresponding to this item
148
148
for (int i = 0 , dest = 0 ; i < ch -> slc_queue_len ; i ++ ) {
149
149
if (ch -> slc_queue [i ] != item ) {
@@ -160,7 +160,7 @@ void ICACHE_FLASH_ATTR i2s_slc_queue_append_item(i2s_state_t *ch, uint32_t *item
160
160
// This routine is called as soon as the DMA routine has something to tell us. All we
161
161
// handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
162
162
// descriptor has the 'EOF' field set to 1.
163
- void ICACHE_FLASH_ATTR i2s_slc_isr (void ) {
163
+ void ICACHE_RAM_ATTR i2s_slc_isr (void ) {
164
164
uint32_t slc_intr_status = SLCIS ;
165
165
SLCIC = 0xFFFFFFFF ;
166
166
if (slc_intr_status & SLCIRXEOF ) {
@@ -172,7 +172,9 @@ void ICACHE_FLASH_ATTR i2s_slc_isr(void) {
172
172
i2s_slc_queue_next_item (tx ); //free space for finished_item
173
173
}
174
174
tx -> slc_queue [tx -> slc_queue_len ++ ] = finished_item -> buf_ptr ;
175
- if (tx -> callback ) tx -> callback ();
175
+ if (tx -> callback ) {
176
+ tx -> callback ();
177
+ }
176
178
ETS_SLC_INTR_ENABLE ();
177
179
}
178
180
if (slc_intr_status & SLCITXEOF ) {
@@ -182,7 +184,9 @@ void ICACHE_FLASH_ATTR i2s_slc_isr(void) {
182
184
finished_item -> owner = 1 ; // Or else RX just stops
183
185
finished_item -> myid ++ ;
184
186
i2s_slc_queue_append_item (rx , finished_item -> buf_ptr );
185
- if (rx -> callback ) rx -> callback ();
187
+ if (rx -> callback ) {
188
+ rx -> callback ();
189
+ }
186
190
ETS_SLC_INTR_ENABLE ();
187
191
}
188
192
}
@@ -195,13 +199,11 @@ void i2s_rx_set_callback(void (*callback) (void)){
195
199
rx -> callback = callback ;
196
200
}
197
201
198
- static void ICACHE_FLASH_ATTR _alloc_channel (i2s_state_t * ch ) {
199
- int x , y ;
200
-
202
+ static void _alloc_channel (i2s_state_t * ch ) {
201
203
ch -> slc_queue_len = 0 ;
202
- for (x = 0 ; x < SLC_BUF_CNT ; x ++ ) {
204
+ for (int x = 0 ; x < SLC_BUF_CNT ; x ++ ) {
203
205
ch -> slc_buf_pntr [x ] = malloc (SLC_BUF_LEN * 4 );
204
- for ( y = 0 ; y < SLC_BUF_LEN ; y ++ ) ch -> slc_buf_pntr [x ][y ] = 0 ;
206
+ memset ( ch -> slc_buf_pntr [ x ], 0 , SLC_BUF_LEN * sizeof ( ch -> slc_buf_pntr [x ][0 ])) ;
205
207
206
208
ch -> slc_items [x ].unused = 0 ;
207
209
ch -> slc_items [x ].owner = 1 ;
@@ -225,7 +227,7 @@ rx->slc_items[i].buf_ptr, rx->slc_items[i].next_link_ptr);
225
227
#endif
226
228
227
229
228
- static void ICACHE_FLASH_ATTR i2s_slc_begin () {
230
+ static void i2s_slc_begin () {
229
231
if (tx ) {
230
232
_alloc_channel (tx );
231
233
}
@@ -242,7 +244,7 @@ static void ICACHE_FLASH_ATTR i2s_slc_begin() {
242
244
SLCC0 &= ~(SLCMM << SLCM ); // Clear DMA MODE
243
245
SLCC0 |= (1 << SLCM ); // Set DMA MODE to 1
244
246
SLCRXDC |= SLCBINR | SLCBTNR ; // Enable INFOR_NO_REPLACE and TOKEN_NO_REPLACE
245
- SLCRXDC &= ~(/*SLCBRXFE |*/ SLCBRXEM | SLCBRXFM ); //disable RX_FILL, RX_EOF_MODE and RX_FILL_MODE
247
+ SLCRXDC &= ~(/*SLCBRXFE |*/ SLCBRXEM | SLCBRXFM ); // Disable RX_FILL, RX_EOF_MODE and RX_FILL_MODE
246
248
247
249
//Feed DMA the 1st buffer desc addr
248
250
//To send data to the I2S subsystem, counter-intuitively we use the RXLINK part, not the TXLINK as you might
@@ -256,7 +258,7 @@ static void ICACHE_FLASH_ATTR i2s_slc_begin() {
256
258
SLCTXL |= (uint32 )& rx -> slc_items [0 ] << SLCTXLA ; // Set real RX address
257
259
}
258
260
if (!tx ) {
259
- // SLCRXL |= (uint32)&rx->slc_items[1] << SLCRXLA; // Set fake (ununsed) TX descriptor address
261
+ SLCRXL |= (uint32 )& rx -> slc_items [1 ] << SLCRXLA ; // Set fake (ununsed) TX descriptor address
260
262
} else {
261
263
SLCRXL |= (uint32 )& tx -> slc_items [0 ] << SLCRXLA ; // Set real TX address
262
264
}
@@ -273,7 +275,7 @@ static void ICACHE_FLASH_ATTR i2s_slc_begin() {
273
275
}
274
276
}
275
277
276
- static void ICACHE_FLASH_ATTR i2s_slc_end (){
278
+ static void i2s_slc_end (){
277
279
ETS_SLC_INTR_DISABLE ();
278
280
SLCIC = 0xFFFFFFFF ;
279
281
SLCIE = 0 ;
@@ -296,7 +298,7 @@ static void ICACHE_FLASH_ATTR i2s_slc_end(){
296
298
//at least the current sample rate. You can also call it quicker: it will suspend the calling
297
299
//thread if the buffer is full and resume when there's room again.
298
300
299
- static bool ICACHE_FLASH_ATTR _i2s_write_sample (uint32_t sample , bool nb ) {
301
+ static bool _i2s_write_sample (uint32_t sample , bool nb ) {
300
302
if (tx -> curr_slc_buf_pos == SLC_BUF_LEN || tx -> curr_slc_buf == NULL ) {
301
303
if (tx -> slc_queue_len == 0 ) {
302
304
if (nb ) return false;
@@ -326,14 +328,14 @@ bool ICACHE_FLASH_ATTR i2s_write_sample_nb(uint32_t sample) {
326
328
return _i2s_write_sample (sample , true);
327
329
}
328
330
329
- bool ICACHE_FLASH_ATTR i2s_write_lr (int16_t left , int16_t right ){
331
+ bool i2s_write_lr (int16_t left , int16_t right ){
330
332
int sample = right & 0xFFFF ;
331
333
sample = sample << 16 ;
332
334
sample |= left & 0xFFFF ;
333
335
return i2s_write_sample (sample );
334
336
}
335
337
336
- bool ICACHE_FLASH_ATTR i2s_read_sample (uint32_t * left , uint32_t * right , bool blocking ) {
338
+ bool i2s_read_sample (uint32_t * left , uint32_t * right , bool blocking ) {
337
339
if (rx -> curr_slc_buf_pos == SLC_BUF_LEN || rx -> curr_slc_buf == NULL ) {
338
340
if (rx -> slc_queue_len == 0 ) {
339
341
if (!blocking ) return false;
@@ -352,22 +354,15 @@ bool ICACHE_FLASH_ATTR i2s_read_sample(uint32_t *left, uint32_t *right, bool blo
352
354
rx -> curr_slc_buf_pos = 0 ;
353
355
}
354
356
355
- // *left = rx->slc_items[0].buf_ptr[rx->curr_slc_buf_pos++];
356
- // *right = rx->slc_items[0].buf_ptr[rx->curr_slc_buf_pos++];
357
357
* left = rx -> curr_slc_buf [rx -> curr_slc_buf_pos ++ ];
358
358
* right = rx -> curr_slc_buf [rx -> curr_slc_buf_pos ++ ];
359
359
360
360
return true;
361
361
}
362
362
363
- // END DMA
364
- // =========
365
- // START I2S
366
-
367
-
368
363
static uint32_t _i2s_sample_rate ;
369
364
370
- void ICACHE_FLASH_ATTR i2s_set_rate (uint32_t rate ){ //Rate in HZ
365
+ void i2s_set_rate (uint32_t rate ){ //Rate in HZ
371
366
if (rate == _i2s_sample_rate ) return ;
372
367
_i2s_sample_rate = rate ;
373
368
@@ -392,19 +387,19 @@ void ICACHE_FLASH_ATTR i2s_set_rate(uint32_t rate){ //Rate in HZ
392
387
I2SC |= I2SRF | I2SMR | I2SRMS | ((sbd_div_best ) << I2SBD ) | ((scd_div_best ) << I2SCD );
393
388
}
394
389
395
- void ICACHE_FLASH_ATTR i2s_set_dividers (uint8_t div1 , uint8_t div2 ){
390
+ void i2s_set_dividers (uint8_t div1 , uint8_t div2 ){
396
391
div1 &= I2SBDM ;
397
392
div2 &= I2SCDM ;
398
393
399
394
I2SC &= ~(I2STSM | I2SRSM | (I2SBMM << I2SBM ) | (I2SBDM << I2SBD ) | (I2SCDM << I2SCD ));
400
395
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | (div1 << I2SBD ) | (div2 << I2SCD );
401
396
}
402
397
403
- float ICACHE_FLASH_ATTR i2s_get_real_rate (){
398
+ float i2s_get_real_rate (){
404
399
return (float )I2SBASEFREQ /32 /((I2SC >>I2SBD ) & I2SBDM )/((I2SC >> I2SCD ) & I2SCDM );
405
400
}
406
401
407
- void ICACHE_FLASH_ATTR i2s_rxtx_begin (bool enableRx , bool enableTx ) {
402
+ void i2s_rxtx_begin (bool enableRx , bool enableTx ) {
408
403
if (tx || rx ) {
409
404
i2s_end (); // Stop and free any ongoing stuff
410
405
}
@@ -414,9 +409,9 @@ void ICACHE_FLASH_ATTR i2s_rxtx_begin(bool enableRx, bool enableTx) {
414
409
if (!tx ) {
415
410
return ; // OOM Error!
416
411
}
417
- pinMode (2 , FUNCTION_1 ); // I2SO_WS (LRCK)
418
- pinMode (3 , FUNCTION_1 ); // I2SO_DATA (SDIN)
419
- pinMode (15 , FUNCTION_1 ); // I2SO_BCK (SCLK)
412
+ pinMode (I2SO_WS , FUNCTION_1 );
413
+ pinMode (I2SO_DATA , FUNCTION_1 );
414
+ pinMode (I2SO_BCK , FUNCTION_1 );
420
415
}
421
416
if (enableRx ) {
422
417
rx = (i2s_state_t * )calloc (1 , sizeof (* rx ));
@@ -460,24 +455,24 @@ void ICACHE_FLASH_ATTR i2s_rxtx_begin(bool enableRx, bool enableTx) {
460
455
I2SC |= (rx ?I2SRXS :0 ) | (tx ?I2STXS :0 ); // Start transmission/reception
461
456
}
462
457
463
- void ICACHE_FLASH_ATTR i2s_begin () {
458
+ void i2s_begin () {
464
459
i2s_rxtx_begin (false, true);
465
460
}
466
461
467
- void ICACHE_FLASH_ATTR i2s_end () {
462
+ void i2s_end () {
468
463
I2SC &= ~I2STXS ;
469
464
470
- //Reset I2S
465
+ // Reset I2S
471
466
I2SC &= ~(I2SRST );
472
467
I2SC |= I2SRST ;
473
468
I2SC &= ~(I2SRST );
474
469
475
470
i2s_slc_end ();
476
471
477
472
if (tx ) {
478
- pinMode (2 , INPUT );
479
- pinMode (3 , INPUT );
480
- pinMode (15 , INPUT );
473
+ pinMode (I2SO_DATA , INPUT );
474
+ pinMode (I2SO_BCK , INPUT );
475
+ pinMode (I2SO_WS , INPUT );
481
476
free (tx );
482
477
tx = NULL ;
483
478
}
0 commit comments