Skip to content
Prev Previous commit
Next Next commit
fixed i2s_set_rate, added i2s_get_real_rate() and i2s_set_dividers
  • Loading branch information
Kristijan Gjoshev committed Jan 17, 2018
commit 941e68e484d9ca0438b7ed94750f6e78d4d53f6e
33 changes: 30 additions & 3 deletions cores/esp8266/core_esp8266_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,42 @@ static uint32_t _i2s_sample_rate;
void ICACHE_FLASH_ATTR i2s_set_rate(uint32_t rate){ //Rate in HZ
if(rate == _i2s_sample_rate) return;
_i2s_sample_rate = rate;
uint32_t i2s_clock_div = (I2SBASEFREQ/(_i2s_sample_rate*32)) & I2SCDM;
uint8_t i2s_bck_div = (I2SBASEFREQ/(_i2s_sample_rate*i2s_clock_div*2)) & I2SBDM;

uint32_t scaled_base_freq = I2SBASEFREQ/32;
float delta_best = scaled_base_freq;

uint8_t sbd_div_best=1;
uint8_t scd_div_best=1;
for (uint8_t i=1; i<64; i++){
for (uint8_t j=i; j<64; j++){
if (fabs(((float)scaled_base_freq/i/j) - rate) < delta_best){
delta_best = fabs(((float)scaled_base_freq/i/j) - rate);
sbd_div_best = i;
scd_div_best = j;
}
}
}

//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));

//!trans master, !bits mod, rece slave mod, rece msb shift, right first, msb right
I2SC &= ~(I2STSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD));
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | ((i2s_bck_div) << I2SBD) | ((i2s_clock_div) << I2SCD);
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | ((sbd_div_best) << I2SBD) | ((scd_div_best) << I2SCD);
}

void ICACHE_FLASH_ATTR i2s_set_dividers(uint8_t div1, uint8_t div2){
div1 &= I2SBDM;
div2 &= I2SCDM;

I2SC &= ~(I2STSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD));
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | (div1 << I2SBD) | (div2 << I2SCD);
}

float ICACHE_FLASH_ATTR i2s_get_real_rate(){
return (float)I2SBASEFREQ/32/((I2SC>>I2SBD) & I2SBDM)/((I2SC >> I2SCD) & I2SCDM);
}


void ICACHE_FLASH_ATTR i2s_begin(){
_i2s_sample_rate = 0;
i2s_slc_begin();
Expand Down
4 changes: 3 additions & 1 deletion cores/esp8266/i2s.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ extern "C" {
void i2s_begin();
void i2s_end();
void i2s_set_rate(uint32_t rate);//Sample Rate in Hz (ex 44100, 48000)
void i2s_set_dividers(uint8_t div1, uint8_t div2);//Direct control over output rate
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
Expand All @@ -54,4 +56,4 @@ int16_t i2s_available();// returns the number of samples than can be written bef
}
#endif

#endif
#endif