Skip to content

Commit cf21dfd

Browse files
aguavivadevyte
authored andcommitted
i2s can send now buffers (#5349)
* i2s can send now buffers * adding mono and stereo, with blocking and non blocking support * fixing crash * cosmetic changes * we dont need the & 0xffff * using unsigned integers since we'll never be using negative numbers
1 parent 19a0a0b commit cf21dfd

File tree

2 files changed

+80
-5
lines changed

2 files changed

+80
-5
lines changed

cores/esp8266/core_esp8266_i2s.c

+71-3
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,18 @@ bool i2s_rx_is_empty() {
113113
return _i2s_is_empty( rx );
114114
}
115115

116-
static int16_t _i2s_available(const i2s_state_t *ch) {
116+
static uint16_t _i2s_available(const i2s_state_t *ch) {
117117
if (!ch) {
118118
return 0;
119119
}
120120
return (SLC_BUF_CNT - ch->slc_queue_len) * SLC_BUF_LEN;
121121
}
122122

123-
int16_t i2s_available(){
123+
uint16_t i2s_available(){
124124
return _i2s_available( tx );
125125
}
126126

127-
int16_t i2s_rx_available(){
127+
uint16_t i2s_rx_available(){
128128
return _i2s_available( rx );
129129
}
130130

@@ -331,6 +331,74 @@ bool i2s_write_lr(int16_t left, int16_t right){
331331
return i2s_write_sample(sample);
332332
}
333333

334+
// writes a buffer of frames into the DMA memory, returns the amount of frames written
335+
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
336+
static uint16_t _i2s_write_buffer(int16_t *frames, uint16_t frame_count, bool mono, bool nb) {
337+
uint16_t frames_written=0;
338+
339+
while(frame_count>0) {
340+
341+
// make sure we have room in the current buffer
342+
if (tx->curr_slc_buf_pos==SLC_BUF_LEN || tx->curr_slc_buf==NULL) {
343+
// no room in the current buffer? if there are no buffers available then exit
344+
if (tx->slc_queue_len == 0)
345+
{
346+
if (nb) {
347+
// if nonblocking just return the number of frames written so far
348+
break;
349+
}
350+
else {
351+
while (1) {
352+
if (tx->slc_queue_len > 0) {
353+
break;
354+
} else {
355+
optimistic_yield(10000);
356+
}
357+
}
358+
}
359+
}
360+
361+
// get a new buffer
362+
ETS_SLC_INTR_DISABLE();
363+
tx->curr_slc_buf = (uint32_t *)i2s_slc_queue_next_item(tx);
364+
ETS_SLC_INTR_ENABLE();
365+
tx->curr_slc_buf_pos=0;
366+
}
367+
368+
//space available in the current buffer
369+
uint16_t available = SLC_BUF_LEN - tx->curr_slc_buf_pos;
370+
371+
uint16_t fc = (available < frame_count) ? available : frame_count;
372+
373+
if (mono) {
374+
for(uint16_t i=0;i<fc;i++){
375+
uint16_t v = (uint16_t)(*frames++);
376+
tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v << 16) | v;
377+
}
378+
}
379+
else
380+
{
381+
for(uint16_t i=0;i<fc;i++){
382+
uint16_t v1 = (uint16_t)(*frames++);
383+
uint16_t v2 = (uint16_t)(*frames++);
384+
tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | v2;
385+
}
386+
}
387+
388+
frame_count -= fc;
389+
frames_written += fc;
390+
}
391+
return frames_written;
392+
}
393+
394+
uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); }
395+
396+
uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); }
397+
398+
uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); }
399+
400+
uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); }
401+
334402
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) {
335403
if (!rx) {
336404
return false;

cores/esp8266/i2s.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,18 @@ bool i2s_is_full();//returns true if DMA is full and can not take more bytes (ov
5454
bool i2s_is_empty();//returns true if DMA is empty (underflow)
5555
bool i2s_rx_is_full();
5656
bool i2s_rx_is_empty();
57-
int16_t i2s_available();// returns the number of samples than can be written before blocking
58-
int16_t i2s_rx_available();// returns the number of samples than can be written before blocking
57+
uint16_t i2s_available();// returns the number of samples than can be written before blocking
58+
uint16_t i2s_rx_available();// returns the number of samples than can be written before blocking
5959
void i2s_set_callback(void (*callback) (void));
6060
void i2s_rx_set_callback(void (*callback) (void));
6161

62+
// writes a buffer of frames into the DMA memory, returns the amount of frames written
63+
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
64+
uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count);
65+
uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count);
66+
uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count);
67+
uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count);
68+
6269
#ifdef __cplusplus
6370
}
6471
#endif

0 commit comments

Comments
 (0)