@@ -73,15 +73,16 @@ static i2s_state_t *tx = NULL;
73
73
volatile uint32_t rx_irqs = 0 ;
74
74
volatile uint32_t tx_irqs = 0 ;
75
75
76
- // Some constants that aren't defined in i2s_regs.h
76
+ // IOs used for I2S. Not defined in i2s.h, unfortunately.
77
+ // Note these are internal IOs numbers and not pins on an
78
+ // Arduino board. Users need to verify their particular wiring.
77
79
#define I2SO_DATA 3
78
80
#define I2SO_BCK 15
79
81
#define I2SO_WS 2
80
82
#define I2SI_DATA 12
81
83
#define I2SI_BCK 13
82
84
#define I2SI_WS 14
83
85
84
-
85
86
static bool _i2s_is_full (const i2s_state_t * ch ) {
86
87
if (!ch ) {
87
88
return false;
@@ -153,22 +154,18 @@ static void ICACHE_RAM_ATTR i2s_slc_queue_append_item(i2s_state_t *ch, uint32_t
153
154
}
154
155
}
155
156
156
- // This routine is called as soon as the DMA routine has something to tell us. All we
157
- // handle here is the *_EOF_INT status, which indicate the DMA has finished a buffer whose
158
- // descriptor has the 'EOF' field set to 1.
159
157
void ICACHE_RAM_ATTR i2s_slc_isr (void ) {
160
158
ETS_SLC_INTR_DISABLE ();
161
- // TODO - Seems like there's a chance of missed IRQ notification because the clear happens at least 1 cycle
162
- // after the status read. Not sure if there's a HW way to prevernt this, even atomic SWAP
163
- // won't help since these are 2 separate addresses. Ugh!
164
159
uint32_t slc_intr_status = SLCIS ;
165
160
SLCIC = 0xFFFFFFFF ;
166
161
if (slc_intr_status & SLCIRXEOF ) {
167
162
tx_irqs ++ ;
168
163
slc_queue_item_t * finished_item = (slc_queue_item_t * )SLCRXEDA ;
169
- memset ((void * )finished_item -> buf_ptr , 0x00 , SLC_BUF_LEN * 4 );//zero the buffer so it is mute in case of underflow
170
- if (tx -> slc_queue_len >= SLC_BUF_CNT - 1 ) { //All buffers are empty. This means we have an underflow
171
- i2s_slc_queue_next_item (tx ); //free space for finished_item
164
+ // Zero the buffer so it is mute in case of underflow
165
+ ets_memset ((void * )finished_item -> buf_ptr , 0x00 , SLC_BUF_LEN * 4 );
166
+ if (tx -> slc_queue_len >= SLC_BUF_CNT - 1 ) {
167
+ // All buffers are empty. This means we have an underflow
168
+ i2s_slc_queue_next_item (tx ); // Free space for finished_item
172
169
}
173
170
tx -> slc_queue [tx -> slc_queue_len ++ ] = finished_item -> buf_ptr ;
174
171
if (tx -> callback ) {
@@ -178,7 +175,8 @@ void ICACHE_RAM_ATTR i2s_slc_isr(void) {
178
175
if (slc_intr_status & SLCITXEOF ) {
179
176
rx_irqs ++ ;
180
177
slc_queue_item_t * finished_item = (slc_queue_item_t * )SLCTXEDA ;
181
- finished_item -> owner = 1 ; // Or else RX just stops
178
+ // Set owner back to 1 (SW) or else RX stops. TX has no such restriction.
179
+ finished_item -> owner = 1 ;
182
180
i2s_slc_queue_append_item (rx , finished_item -> buf_ptr );
183
181
if (rx -> callback ) {
184
182
rx -> callback ();
@@ -211,6 +209,7 @@ static void _alloc_channel(i2s_state_t *ch) {
211
209
ch -> slc_items [x ].next_link_ptr = (x < (SLC_BUF_CNT - 1 ))?(& ch -> slc_items [x + 1 ]):(& ch -> slc_items [0 ]);
212
210
}
213
211
}
212
+
214
213
#if 0
215
214
void dumprx ()
216
215
{
@@ -221,7 +220,6 @@ rx->slc_items[i].buf_ptr, rx->slc_items[i].next_link_ptr);
221
220
}
222
221
#endif
223
222
224
-
225
223
static void i2s_slc_begin () {
226
224
if (tx ) {
227
225
_alloc_channel (tx );
@@ -375,17 +373,23 @@ void i2s_set_rate(uint32_t rate){ //Rate in HZ
375
373
}
376
374
}
377
375
378
- //!trans master, !bits mod, rece slave mod, rece msb shift, right first, msb right
379
- I2SC &= ~(I2STSM | I2SRSM | /*(I2SBMM << I2SBM) |*/ (I2SBDM << I2SBD ) | (I2SCDM << I2SCD ));
380
- I2SC |= I2SRF | I2SMR | I2SRMS | ((sbd_div_best ) << I2SBD ) | ((scd_div_best ) << I2SCD );
376
+ i2s_set_dividers ( sbd_div_best , scd_div_best );
381
377
}
382
378
383
- void i2s_set_dividers (uint8_t div1 , uint8_t div2 ){
379
+ void i2s_set_dividers (uint8_t div1 , uint8_t div2 ) {
380
+ // Ensure dividers fit in bit fields
384
381
div1 &= I2SBDM ;
385
382
div2 &= I2SCDM ;
386
383
387
- I2SC &= ~(I2STSM | I2SRSM | (I2SBMM << I2SBM ) | (I2SBDM << I2SBD ) | (I2SCDM << I2SCD ));
388
- I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | (div1 << I2SBD ) | (div2 << I2SCD );
384
+ // !trans master(?), !bits mod(==16 bits/chanel), clear clock dividers
385
+ I2SC &= ~(I2STSM | (I2SBMM << I2SBM ) | (I2SBDM << I2SBD ) | (I2SCDM << I2SCD ));
386
+
387
+ // I2SRF = Send/recv right channel first (? may be swapped form I2S spec of WS=0 => left)
388
+ // I2SMR = MSB recv/xmit first
389
+ // I2SRSM = Receive slave mode (?)
390
+ // I2SRMS, I2STMS = 1-bit delay from WS to MSB (I2S format)
391
+ // div1, div2 = Set I2S WS clock frequency. BCLK seems to be generated from 32x this
392
+ I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | I2STMS | (div1 << I2SBD ) | (div2 << I2SCD );
389
393
}
390
394
391
395
float i2s_get_real_rate (){
@@ -433,9 +437,11 @@ void i2s_rxtx_begin(bool enableRx, bool enableTx) {
433
437
I2SC |= I2SRST ;
434
438
I2SC &= ~(I2SRST );
435
439
440
+ // I2STXFMM, I2SRXFMM=0 => 16-bit, dual channel data shifted in/out
436
441
I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM ) | (I2SRXFMM << I2SRXFM )); // Set RX/TX FIFO_MOD=0 and disable DMA (FIFO only)
437
442
I2SFC |= I2SDE | (rx ? 2 /*24bpc, 2ch*/ <<I2SRXFM : 0 ); // Enable DMA, set RX format 24(32bits), 2 channels
438
443
444
+ // I2STXCMM, I2SRXCMM=0 => Dual channel mode
439
445
I2SCC &= ~((I2STXCMM << I2STXCM ) | (I2SRXCMM << I2SRXCM )); // Set RX/TX CHAN_MOD=0
440
446
441
447
i2s_set_rate (44100 );
@@ -453,7 +459,9 @@ void i2s_begin() {
453
459
}
454
460
455
461
void i2s_end () {
456
- I2SC &= ~I2STXS ;
462
+ // Disable any I2S send or receive
463
+ // ? Maybe not needed since we're resetting on the next line...
464
+ I2SC &= ~(I2STXS | I2SRXS );
457
465
458
466
// Reset I2S
459
467
I2SC &= ~(I2SRST );
0 commit comments