Skip to content

Commit 0fe7259

Browse files
Crypterearlephilhower
authored andcommitted
Update I2S base frequency and frequency dividers to real ones (#4031)
* Fix I2S base frequency * Update frequency dividers for I2S Reference: https://github.com/espressif/ESP8266_MP3_DECODER/blob/master/mp3/driver/i2s_freertos.c * fixed i2s_set_rate, added i2s_get_real_rate() and i2s_set_dividers * Minimise float calculations
1 parent 38fe6fc commit 0fe7259

File tree

3 files changed

+35
-5
lines changed

3 files changed

+35
-5
lines changed

cores/esp8266/core_esp8266_i2s.c

+31-3
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,43 @@ static uint32_t _i2s_sample_rate;
212212
void ICACHE_FLASH_ATTR i2s_set_rate(uint32_t rate){ //Rate in HZ
213213
if(rate == _i2s_sample_rate) return;
214214
_i2s_sample_rate = rate;
215-
uint32_t i2s_clock_div = (I2SBASEFREQ/(_i2s_sample_rate*32)) & I2SCDM;
216-
uint8_t i2s_bck_div = (I2SBASEFREQ/(_i2s_sample_rate*i2s_clock_div*2)) & I2SBDM;
215+
216+
uint32_t scaled_base_freq = I2SBASEFREQ/32;
217+
float delta_best = scaled_base_freq;
218+
219+
uint8_t sbd_div_best=1;
220+
uint8_t scd_div_best=1;
221+
for (uint8_t i=1; i<64; i++){
222+
for (uint8_t j=i; j<64; j++){
223+
float new_delta = fabs(((float)scaled_base_freq/i/j) - rate);
224+
if (new_delta < delta_best){
225+
delta_best = new_delta;
226+
sbd_div_best = i;
227+
scd_div_best = j;
228+
}
229+
}
230+
}
231+
217232
//os_printf("Rate %u Div %u Bck %u Frq %u\n", _i2s_sample_rate, i2s_clock_div, i2s_bck_div, I2SBASEFREQ/(i2s_clock_div*i2s_bck_div*2));
218233

219234
//!trans master, !bits mod, rece slave mod, rece msb shift, right first, msb right
220235
I2SC &= ~(I2STSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD));
221-
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | ((i2s_bck_div-1) << I2SBD) | ((i2s_clock_div-1) << I2SCD);
236+
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | ((sbd_div_best) << I2SBD) | ((scd_div_best) << I2SCD);
237+
}
238+
239+
void ICACHE_FLASH_ATTR i2s_set_dividers(uint8_t div1, uint8_t div2){
240+
div1 &= I2SBDM;
241+
div2 &= I2SCDM;
242+
243+
I2SC &= ~(I2STSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD));
244+
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | (div1 << I2SBD) | (div2 << I2SCD);
222245
}
223246

247+
float ICACHE_FLASH_ATTR i2s_get_real_rate(){
248+
return (float)I2SBASEFREQ/32/((I2SC>>I2SBD) & I2SBDM)/((I2SC >> I2SCD) & I2SCDM);
249+
}
250+
251+
224252
void ICACHE_FLASH_ATTR i2s_begin(){
225253
_i2s_sample_rate = 0;
226254
i2s_slc_begin();

cores/esp8266/esp8266_peri.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ extern uint8_t esp8266_gpioToFn[16];
754754
#define i2c_bbpll_en_audio_clock_out_msb 7
755755
#define i2c_bbpll_en_audio_clock_out_lsb 7
756756
#define I2S_CLK_ENABLE() i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1)
757-
#define I2SBASEFREQ (12000000L)
757+
#define I2SBASEFREQ (160000000L)
758758

759759
#define I2STXF ESP8266_REG(0xe00) //I2STXFIFO (32bit)
760760
#define I2SRXF ESP8266_REG(0xe04) //I2SRXFIFO (32bit)

cores/esp8266/i2s.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ extern "C" {
4343
void i2s_begin();
4444
void i2s_end();
4545
void i2s_set_rate(uint32_t rate);//Sample Rate in Hz (ex 44100, 48000)
46+
void i2s_set_dividers(uint8_t div1, uint8_t div2);//Direct control over output rate
47+
float i2s_get_real_rate();//The actual Sample Rate on output
4648
bool i2s_write_sample(uint32_t sample);//32bit sample with channels being upper and lower 16 bits (blocking when DMA is full)
4749
bool i2s_write_sample_nb(uint32_t sample);//same as above but does not block when DMA is full and returns false instead
4850
bool i2s_write_lr(int16_t left, int16_t right);//combines both channels and calls i2s_write_sample with the result
@@ -54,4 +56,4 @@ int16_t i2s_available();// returns the number of samples than can be written bef
5456
}
5557
#endif
5658

57-
#endif
59+
#endif

0 commit comments

Comments
 (0)