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

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
This commit is contained in:
aguaviva 2018-11-24 06:00:34 +01:00 committed by Develo
parent 19a0a0b6fd
commit cf21dfda64
2 changed files with 80 additions and 5 deletions

View File

@ -113,18 +113,18 @@ bool i2s_rx_is_empty() {
return _i2s_is_empty( rx ); return _i2s_is_empty( rx );
} }
static int16_t _i2s_available(const i2s_state_t *ch) { static uint16_t _i2s_available(const i2s_state_t *ch) {
if (!ch) { if (!ch) {
return 0; return 0;
} }
return (SLC_BUF_CNT - ch->slc_queue_len) * SLC_BUF_LEN; return (SLC_BUF_CNT - ch->slc_queue_len) * SLC_BUF_LEN;
} }
int16_t i2s_available(){ uint16_t i2s_available(){
return _i2s_available( tx ); return _i2s_available( tx );
} }
int16_t i2s_rx_available(){ uint16_t i2s_rx_available(){
return _i2s_available( rx ); return _i2s_available( rx );
} }
@ -331,6 +331,74 @@ bool i2s_write_lr(int16_t left, int16_t right){
return i2s_write_sample(sample); 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 uint16_t _i2s_write_buffer(int16_t *frames, uint16_t frame_count, bool mono, bool nb) {
uint16_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
uint16_t available = SLC_BUF_LEN - tx->curr_slc_buf_pos;
uint16_t fc = (available < frame_count) ? available : frame_count;
if (mono) {
for(uint16_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(uint16_t i=0;i<fc;i++){
uint16_t v1 = (uint16_t)(*frames++);
uint16_t v2 = (uint16_t)(*frames++);
tx->curr_slc_buf[tx->curr_slc_buf_pos++] = (v1 << 16) | v2;
}
}
frame_count -= fc;
frames_written += fc;
}
return frames_written;
}
uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); }
uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); }
uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); }
uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); }
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) { bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) {
if (!rx) { if (!rx) {
return false; return false;

View File

@ -54,11 +54,18 @@ bool i2s_is_full();//returns true if DMA is full and can not take more bytes (ov
bool i2s_is_empty();//returns true if DMA is empty (underflow) bool i2s_is_empty();//returns true if DMA is empty (underflow)
bool i2s_rx_is_full(); bool i2s_rx_is_full();
bool i2s_rx_is_empty(); bool i2s_rx_is_empty();
int16_t i2s_available();// returns the number of samples than can be written before blocking uint16_t i2s_available();// returns the number of samples than can be written before blocking
int16_t i2s_rx_available();// returns the number of samples than can be written before blocking uint16_t i2s_rx_available();// returns the number of samples than can be written before blocking
void i2s_set_callback(void (*callback) (void)); void i2s_set_callback(void (*callback) (void));
void i2s_rx_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.
uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count);
uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count);
uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count);
uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif