Skip to content
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

Add 24-bit mode to I2S #7835

Merged
merged 2 commits into from
Jan 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion cores/esp8266/core_esp8266_i2s.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static i2s_state_t *tx = NULL;

// Last I2S sample rate requested
static uint32_t _i2s_sample_rate;
static int _i2s_bits = 16;

// IOs used for I2S. Not defined in i2s.h, unfortunately.
// Note these are internal GPIO numbers and not pins on an
Expand All @@ -84,6 +85,14 @@ static uint32_t _i2s_sample_rate;
#define I2SI_BCK 13
#define I2SI_WS 14

bool i2s_set_bits(int bits) {
if (tx || rx || (bits != 16 && bits != 24)) {
return false;
}
_i2s_bits = bits;
return true;
}

static bool _i2s_is_full(const i2s_state_t *ch) {
if (!ch) {
return false;
Expand Down Expand Up @@ -441,7 +450,7 @@ void i2s_set_rate(uint32_t rate) { //Rate in HZ
}
_i2s_sample_rate = rate;

uint32_t scaled_base_freq = I2SBASEFREQ/32;
uint32_t scaled_base_freq = I2SBASEFREQ / (_i2s_bits * 2);
float delta_best = scaled_base_freq;

uint8_t sbd_div_best=1;
Expand Down Expand Up @@ -483,6 +492,9 @@ void i2s_set_dividers(uint8_t div1, uint8_t div2) {
// div1, div2 = Set I2S WS clock frequency. BCLK seems to be generated from 32x this
i2sc_temp |= I2SRF | I2SMR | I2SRMS | I2STMS | (div1 << I2SBD) | (div2 << I2SCD);

// Adjust the shift count for 16/24b output
i2sc_temp |= (_i2s_bits == 24 ? 8 : 0) << I2SBM;

I2SC = i2sc_temp;

i2sc_temp &= ~(I2STXR); // Release reset
Expand Down Expand Up @@ -549,6 +561,9 @@ bool i2s_rxtxdrive_begin(bool enableRx, bool enableTx, bool driveRxClocks, bool

// 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)
if (_i2s_bits == 24) {
I2SFC |= (2 << I2STXFM) | (2 << I2SRXFM);
}
I2SFC |= I2SDE; // Enable DMA

// I2STXCMM, I2SRXCMM=0 => Dual channel mode
Expand Down
5 changes: 5 additions & 0 deletions cores/esp8266/i2s.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
How does this work? Basically, to get sound, you need to:
- Connect an I2S codec to the I2S pins on the ESP.
- Start up a thread that's going to do the sound output
- Call i2s_set_bits() if you want to enable 24-bit mode
- Call i2s_begin()
- Call i2s_set_rate() with the sample rate you want.
- Generate sound and call i2s_write_sample() with 32-bit samples.
Expand All @@ -42,6 +43,10 @@ speed.
extern "C" {
#endif

bool i2s_set_bits(int bits); // Set bits per sample, only 16 or 24 supported. Call before begin.
// Note that in 24 bit mode each sample must be left-aligned (i.e. 0x00000000 .. 0xffffff00) as the
// hardware shifts starting at bit 31, not bit 23.

void i2s_begin(); // Enable TX only, for compatibility
bool i2s_rxtx_begin(bool enableRx, bool enableTx); // Allow TX and/or RX, returns false on OOM error
bool i2s_rxtxdrive_begin(bool enableRx, bool enableTx, bool driveRxClocks, bool driveTxClocks);
Expand Down