Skip to content

Commit

Permalink
Move to 16bps per channel like xmit, clean up
Browse files Browse the repository at this point in the history
Some I2S configuration and DMA tweaks makes 16 bits per sample per
channel work, giving a basically identical interface as xmit.

The received data values now span the full range of +/-32767 as well.
  • Loading branch information
earlephilhower committed Mar 28, 2018
1 parent bc743d0 commit 0039dbc
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 38 deletions.
28 changes: 7 additions & 21 deletions cores/esp8266/core_esp8266_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ typedef struct i2s_state {
static i2s_state_t *rx = NULL;
static i2s_state_t *tx = NULL;

volatile uint32_t rx_irqs = 0;
volatile uint32_t tx_irqs = 0;

// IOs used for I2S. Not defined in i2s.h, unfortunately.
// Note these are internal IOs numbers and not pins on an
// Arduino board. Users need to verify their particular wiring.
Expand Down Expand Up @@ -159,7 +156,6 @@ void ICACHE_RAM_ATTR i2s_slc_isr(void) {
uint32_t slc_intr_status = SLCIS;
SLCIC = 0xFFFFFFFF;
if (slc_intr_status & SLCIRXEOF) {
tx_irqs++;
slc_queue_item_t *finished_item = (slc_queue_item_t *)SLCRXEDA;
// Zero the buffer so it is mute in case of underflow
ets_memset((void *)finished_item->buf_ptr, 0x00, SLC_BUF_LEN * 4);
Expand All @@ -173,7 +169,6 @@ void ICACHE_RAM_ATTR i2s_slc_isr(void) {
}
}
if (slc_intr_status & SLCITXEOF) {
rx_irqs++;
slc_queue_item_t *finished_item = (slc_queue_item_t *)SLCTXEDA;
// Set owner back to 1 (SW) or else RX stops. TX has no such restriction.
finished_item->owner = 1;
Expand Down Expand Up @@ -210,16 +205,6 @@ static void _alloc_channel(i2s_state_t *ch) {
}
}

#if 0
void dumprx()
{
for (int i=0; i<SLC_BUF_CNT; i++) {
printf("%d: %d %d %d %d %d %d %p %p\n", i, 0, rx->slc_items[i].owner, rx->slc_items[i].eof, rx->slc_items[i].sub_sof, rx->slc_items[i].datalen, rx->slc_items[i].blocksize,
rx->slc_items[i].buf_ptr, rx->slc_items[i].next_link_ptr);
}
}
#endif

static void i2s_slc_begin() {
if (tx) {
_alloc_channel(tx);
Expand Down Expand Up @@ -327,7 +312,7 @@ bool i2s_write_lr(int16_t left, int16_t right){
return i2s_write_sample(sample);
}

bool i2s_read_sample(uint32_t *left, uint32_t *right, bool blocking) {
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) {
if (rx->curr_slc_buf_pos==SLC_BUF_LEN || rx->curr_slc_buf==NULL) {
if (rx->slc_queue_len == 0) {
if (!blocking) return false;
Expand All @@ -345,8 +330,9 @@ bool i2s_read_sample(uint32_t *left, uint32_t *right, bool blocking) {
rx->curr_slc_buf_pos=0;
}

*left = rx->curr_slc_buf[rx->curr_slc_buf_pos++];
*right = rx->curr_slc_buf[rx->curr_slc_buf_pos++];
uint32_t sample = rx->curr_slc_buf[rx->curr_slc_buf_pos++];
*left = sample & 0xffff;
*right = sample >> 16;

return true;
}
Expand Down Expand Up @@ -381,7 +367,7 @@ void i2s_set_dividers(uint8_t div1, uint8_t div2) {
div1 &= I2SBDM;
div2 &= I2SCDM;

// !trans master(?), !recv master(?), !bits mod(==16 bits/chanel), clear clock dividers
// trans master(active low), recv master(active_low), !bits mod(==16 bits/chanel), clear clock dividers
I2SC &= ~(I2STSM | I2SRSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD));

// I2SRF = Send/recv right channel first (? may be swapped form I2S spec of WS=0 => left)
Expand Down Expand Up @@ -438,17 +424,17 @@ void i2s_rxtx_begin(bool enableRx, bool enableTx) {

// I2STXFMM, I2SRXFMM=0 => 16-bit, dual channel data shifted in/out
I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM) | (I2SRXFMM << I2SRXFM)); // Set RX/TX FIFO_MOD=0 and disable DMA (FIFO only)
I2SFC |= I2SDE | (rx ? 2/*24bpc, 2ch*/<<I2SRXFM : 0); // Enable DMA, set RX format 24(32bits), 2 channels
I2SFC |= I2SDE; // Enable DMA

// I2STXCMM, I2SRXCMM=0 => Dual channel mode
I2SCC &= ~((I2STXCMM << I2STXCM) | (I2SRXCMM << I2SRXCM)); // Set RX/TX CHAN_MOD=0

i2s_set_rate(44100);

if (rx) {
// Need to prime the # of samples to receive in the engine
I2SRXEN = SLC_BUF_LEN;
}
// I2SC |= (15<<I2SBM);

I2SC |= (rx?I2SRXS:0) | (tx?I2STXS:0); // Start transmission/reception
}
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/i2s.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ float i2s_get_real_rate();//The actual Sample Rate on output
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_read_sample(uint32_t *left, uint32_t *right, bool blocking); // RX data, 2x32 bits, left-aligned
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking); // RX data, 2x32 bits, left-aligned
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)
bool i2s_rx_is_full();
Expand Down
18 changes: 2 additions & 16 deletions libraries/esp8266/examples/I2SInput/I2SInput.ino
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,21 @@
#include <ESP8266WiFi.h>
#include <i2s.h>

void dump() {
Serial.printf("I2SC: %08x\n", I2SC);
Serial.printf("I2SFC: %08x\n", I2SFC);
Serial.printf("I2SCC: %08x\n", I2SCC);
Serial.printf("I2SRXEN: %08x\n", I2SRXEN);
Serial.printf("SLCC0: %08x\n", SLCC0);
Serial.printf("SLCRXDC: %08x\n", SLCRXDC);
Serial.printf("SLCTXL: %08x\n", SLCTXL);
Serial.printf("SLCIE: %08x\n", SLCIE);
}

void setup() {
Serial.begin(115200);
WiFi.forceSleepBegin();
delay(500);

i2s_rxtx_begin(true, false); // Enable I2S RX
i2s_set_rate(11025);
dump();

delay(1000);

while (1) {
uint32_t l, r;
int16_t l, r;
i2s_read_sample(&l, &r, true);
int16_t lh = l >> 16;
int16_t rh = r >> 16;
char withScale[256];
sprintf(withScale, "%d %d", lh, rh);
sprintf(withScale, "%d %d", l, r);
Serial.println(withScale);
yield();
}
Expand Down

0 comments on commit 0039dbc

Please sign in to comment.