Skip to content

Commit bc51c55

Browse files
authored
Merge branch 'master' into vtable_to_flash
2 parents cc58871 + 29580e8 commit bc51c55

File tree

2 files changed

+394
-230
lines changed

2 files changed

+394
-230
lines changed

cores/esp8266/core_esp8266_i2s.c

+49-38
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@
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
5660
static struct slc_queue_item i2s_slc_items[SLC_BUF_CNT]; //I2S DMA buffer descriptors
5761
static uint32_t *i2s_curr_slc_buf=NULL;//current buffer for writing
5862
static 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

216219
static 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

Comments
 (0)