Skip to content

Commit f2eabd6

Browse files
Merge branch 'master' of https://github.com/esp8266/Arduino into i2s_input
2 parents 35fd325 + 29580e8 commit f2eabd6

File tree

2 files changed

+373
-212
lines changed

2 files changed

+373
-212
lines changed

cores/esp8266/core_esp8266_i2s.c

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,16 @@ static i2s_state_t *tx = NULL;
7373
volatile uint32_t rx_irqs = 0;
7474
volatile uint32_t tx_irqs = 0;
7575

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.
7779
#define I2SO_DATA 3
7880
#define I2SO_BCK 15
7981
#define I2SO_WS 2
8082
#define I2SI_DATA 12
8183
#define I2SI_BCK 13
8284
#define I2SI_WS 14
8385

84-
8586
static bool _i2s_is_full(const i2s_state_t *ch) {
8687
if (!ch) {
8788
return false;
@@ -153,22 +154,18 @@ static void ICACHE_RAM_ATTR i2s_slc_queue_append_item(i2s_state_t *ch, uint32_t
153154
}
154155
}
155156

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.
159157
void ICACHE_RAM_ATTR i2s_slc_isr(void) {
160158
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!
164159
uint32_t slc_intr_status = SLCIS;
165160
SLCIC = 0xFFFFFFFF;
166161
if (slc_intr_status & SLCIRXEOF) {
167162
tx_irqs++;
168163
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
172169
}
173170
tx->slc_queue[tx->slc_queue_len++] = finished_item->buf_ptr;
174171
if (tx->callback) {
@@ -178,7 +175,8 @@ void ICACHE_RAM_ATTR i2s_slc_isr(void) {
178175
if (slc_intr_status & SLCITXEOF) {
179176
rx_irqs++;
180177
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;
182180
i2s_slc_queue_append_item(rx, finished_item->buf_ptr);
183181
if (rx->callback) {
184182
rx->callback();
@@ -211,6 +209,7 @@ static void _alloc_channel(i2s_state_t *ch) {
211209
ch->slc_items[x].next_link_ptr = (x<(SLC_BUF_CNT-1))?(&ch->slc_items[x+1]):(&ch->slc_items[0]);
212210
}
213211
}
212+
214213
#if 0
215214
void dumprx()
216215
{
@@ -221,7 +220,6 @@ rx->slc_items[i].buf_ptr, rx->slc_items[i].next_link_ptr);
221220
}
222221
#endif
223222

224-
225223
static void i2s_slc_begin() {
226224
if (tx) {
227225
_alloc_channel(tx);
@@ -375,17 +373,23 @@ void i2s_set_rate(uint32_t rate){ //Rate in HZ
375373
}
376374
}
377375

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 );
381377
}
382378

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
384381
div1 &= I2SBDM;
385382
div2 &= I2SCDM;
386383

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);
389393
}
390394

391395
float i2s_get_real_rate(){
@@ -433,9 +437,11 @@ void i2s_rxtx_begin(bool enableRx, bool enableTx) {
433437
I2SC |= I2SRST;
434438
I2SC &= ~(I2SRST);
435439

440+
// I2STXFMM, I2SRXFMM=0 => 16-bit, dual channel data shifted in/out
436441
I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM) | (I2SRXFMM << I2SRXFM)); // Set RX/TX FIFO_MOD=0 and disable DMA (FIFO only)
437442
I2SFC |= I2SDE | (rx ? 2/*24bpc, 2ch*/<<I2SRXFM : 0); // Enable DMA, set RX format 24(32bits), 2 channels
438443

444+
// I2STXCMM, I2SRXCMM=0 => Dual channel mode
439445
I2SCC &= ~((I2STXCMM << I2STXCM) | (I2SRXCMM << I2SRXCM)); // Set RX/TX CHAN_MOD=0
440446

441447
i2s_set_rate(44100);
@@ -453,7 +459,9 @@ void i2s_begin() {
453459
}
454460

455461
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);
457465

458466
// Reset I2S
459467
I2SC &= ~(I2SRST);

0 commit comments

Comments
 (0)