1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-11 15:22:13 +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:
Earle F. Philhower, III
2021-01-23 14:40:29 -08:00
committed by GitHub
parent b3fe0aab19
commit e0cfb5a995
2 changed files with 21 additions and 1 deletions

View File

@ -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