Skip to content

i2s can send now buffers #5349

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Nov 24, 2018
68 changes: 68 additions & 0 deletions cores/esp8266/core_esp8266_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,74 @@ bool i2s_write_lr(int16_t left, int16_t right){
return i2s_write_sample(sample);
}

// writes a buffer of frames into the DMA memory, returns the amount of frames written
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
static int16_t _i2s_write_buffer(int16_t *frames, int16_t frame_count, bool mono, bool nb) {
int16_t frames_written=0;

while(frame_count>0) {

// make sure we have room in the current buffer
if (tx->curr_slc_buf_pos==SLC_BUF_LEN || tx->curr_slc_buf==NULL) {
// no room in the current buffer? if there are no buffers available then exit
if (tx->slc_queue_len == 0)
{
if (nb) {
// if nonblocking just return the number of frames written so far
break;
}
else {
while (1) {
if (tx->slc_queue_len > 0) {
break;
} else {
optimistic_yield(10000);
}
}
}
}

// get a new buffer
ETS_SLC_INTR_DISABLE();
tx->curr_slc_buf = (uint32_t *)i2s_slc_queue_next_item(tx);
ETS_SLC_INTR_ENABLE();
tx->curr_slc_buf_pos=0;
}

//space available in the current buffer
int16_t available = SLC_BUF_LEN - tx->curr_slc_buf_pos;

int16_t fc = (available < frame_count) ? available : frame_count;

if (mono) {
for(int16_t i=0;i<fc;i++){
uint16_t v = (uint16_t)(*frames++);
tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | v;
}
}
else
{
for(int16_t i=0;i<fc;i++){
uint16_t v1 = *frames++;
uint16_t v2 = *frames++;
tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | v2;
}
}

frame_count -= fc;
frames_written += fc;
}
return frames_written;
}

int16_t i2s_write_buffer_mono_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); }

int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); }

int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); }

int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); }

bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) {
if (!rx) {
return false;
Expand Down
7 changes: 7 additions & 0 deletions cores/esp8266/i2s.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ int16_t i2s_rx_available();// returns the number of samples than can be written
void i2s_set_callback(void (*callback) (void));
void i2s_rx_set_callback(void (*callback) (void));

// writes a buffer of frames into the DMA memory, returns the amount of frames written
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
int16_t i2s_write_buffer_mono(int16_t *frames, int16_t frame_count);
int16_t i2s_write_buffer_mono_nb(int16_t *frames, int16_t frame_count);
int16_t i2s_write_buffer(int16_t *frames, int16_t frame_count);
int16_t i2s_write_buffer_nb(int16_t *frames, int16_t frame_count);

#ifdef __cplusplus
}
#endif
Expand Down