1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Merge pull request #939 from me-no-dev/esp8266

I2S Optimizations
This commit is contained in:
Ivan Grokhotkov 2015-10-29 12:09:01 +03:00
commit 342c4ae6fb
2 changed files with 31 additions and 6 deletions

View File

@ -54,6 +54,16 @@ static uint32_t i2s_slc_queue[SLC_BUF_CNT-1];
static uint8_t i2s_slc_queue_len;
static uint32_t *i2s_slc_buf_pntr[SLC_BUF_CNT]; //Pointer to the I2S DMA buffer data
static struct slc_queue_item i2s_slc_items[SLC_BUF_CNT]; //I2S DMA buffer descriptors
static uint32_t *i2s_curr_slc_buf=NULL;//current buffer for writing
static int i2s_curr_slc_buf_pos=0; //position in the current buffer
bool ICACHE_FLASH_ATTR i2s_is_full(){
return (i2s_curr_slc_buf_pos==SLC_BUF_LEN || i2s_curr_slc_buf==NULL) && (i2s_slc_queue_len == 0);
}
bool ICACHE_FLASH_ATTR i2s_is_empty(){
return (i2s_slc_queue_len >= SLC_BUF_CNT-1);
}
uint32_t ICACHE_FLASH_ATTR i2s_slc_queue_next_item(){ //pop the top off the queue
uint8_t i;
@ -73,7 +83,7 @@ void ICACHE_FLASH_ATTR i2s_slc_isr(void) {
if (slc_intr_status & SLCIRXEOF) {
ETS_SLC_INTR_DISABLE();
struct slc_queue_item *finished_item = (struct slc_queue_item*)SLCRXEDA;
memset((void *)finished_item->buf_ptr, 0x00, SLC_BUF_LEN * 4);//zero the buffer so it is mute in case of underflow
if (i2s_slc_queue_len >= SLC_BUF_CNT-1) { //All buffers are empty. This means we have an underflow
i2s_slc_queue_next_item(); //free space for finished_item
}
@ -142,8 +152,6 @@ void ICACHE_FLASH_ATTR i2s_slc_end(){
//at least the current sample rate. You can also call it quicker: it will suspend the calling
//thread if the buffer is full and resume when there's room again.
static uint32_t *i2s_curr_slc_buf=NULL;
static int i2s_curr_slc_buf_pos=0;
bool ICACHE_FLASH_ATTR i2s_write_sample(uint32_t sample) {
if (i2s_curr_slc_buf_pos==SLC_BUF_LEN || i2s_curr_slc_buf==NULL) {
if(i2s_slc_queue_len == 0){
@ -165,6 +173,20 @@ bool ICACHE_FLASH_ATTR i2s_write_sample(uint32_t sample) {
return true;
}
bool ICACHE_FLASH_ATTR i2s_write_sample_nb(uint32_t sample) {
if (i2s_curr_slc_buf_pos==SLC_BUF_LEN || i2s_curr_slc_buf==NULL) {
if(i2s_slc_queue_len == 0){
return false;
}
ETS_SLC_INTR_DISABLE();
i2s_curr_slc_buf = (uint32_t *)i2s_slc_queue_next_item();
ETS_SLC_INTR_ENABLE();
i2s_curr_slc_buf_pos=0;
}
i2s_curr_slc_buf[i2s_curr_slc_buf_pos++]=sample;
return true;
}
bool ICACHE_FLASH_ATTR i2s_write_lr(int16_t left, int16_t right){
int sample = right & 0xFFFF;
sample = sample << 16;

View File

@ -42,9 +42,12 @@ extern "C" {
void i2s_begin();
void i2s_end();
void i2s_set_rate(uint32_t rate);
bool i2s_write_sample(uint32_t sample);
bool i2s_write_lr(int16_t left, int16_t right);
void i2s_set_rate(uint32_t rate);//Sample Rate in Hz (ex 44100, 48000)
bool i2s_write_sample(uint32_t sample);//32bit sample with channels being upper and lower 16 bits (blocking when DMA is full)
bool i2s_write_sample_nb(uint32_t sample);//same as above but does not block when DMA is full and returns false instead
bool i2s_write_lr(int16_t left, int16_t right);//combines both channels and calls i2s_write_sample with the result
bool i2s_is_full();//returns true if DMA is full and can not take more bytes (overflow)
bool i2s_is_empty();//returns true if DMA is empty (underflow)
#ifdef __cplusplus
}