mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Add 24-bit mode to I2S (#7835)
Add basic 24 bit mode to the I2S API with a i2s_set_bits() call. By default 16b mode is still used, but if i2s_set_bits(24) is run before i2s_begin() then the HW will drive 24-bits of data. This data must be left-aligned (i.e. bits 31..8) in 4-byte samples. Fixes #5244 (the HW doesn't support 8 or 32 bits, only 16 or 24).
This commit is contained in:
parent
b3fe0aab19
commit
e0cfb5a995
@ -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
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -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
|
||||
|
@ -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.
|
||||
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user