Il y avait des problèmes dans la libraire...
Fork of ST_I2S by
Diff: targets/TARGET_STM/stm_i2s_api.c
- Revision:
- 22:e04af8667cad
- Parent:
- 21:7cf6b1538d29
- Child:
- 23:6ebde375d2d1
--- a/targets/TARGET_STM/stm_i2s_api.c Mon Jan 30 15:13:59 2017 +0100 +++ b/targets/TARGET_STM/stm_i2s_api.c Tue Jan 31 11:30:06 2017 +0100 @@ -345,8 +345,7 @@ handle->Init.Mode = i2s_get_mode(mode, &dma_direction); handle->Init.Standard = I2S_STANDARD_PCM_SHORT; handle->Init.DataFormat = I2S_DATAFORMAT_16B; - handle->Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; // WAS: (mclk == NC ? I2S_MCLKOUTPUT_DISABLE : I2S_MCLKOUTPUT_ENABLE); - // Simplifies harmonization (TO BE IMPROVED)! + handle->Init.MCLKOutput = (mclk == NC ? I2S_MCLKOUTPUT_DISABLE : I2S_MCLKOUTPUT_ENABLE); handle->Init.AudioFreq = I2S_AUDIOFREQ_44K; handle->Init.CPOL = I2S_CPOL_LOW; handle->Init.ClockSource = I2S_CLOCK_PLL; @@ -855,6 +854,16 @@ return i2s_compute_closest_frequency(dev_i2s, hi2s->Init.AudioFreq); } +static inline bool i2s_has_mclk(i2s_t *dev_i2s) +{ + I2S_HandleTypeDef *hi2s; + + /* Get the I2S handle. */ + hi2s = i2s_get_handle(dev_i2s); + + return (hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE); +} + /** Computing the harmonized frequencies of two I2S peripherals. * * @param[in] i2s_t_l reference to the i2s_t structure with the lower frequency. @@ -866,12 +875,8 @@ * @return "0" if the frequencies have been harmonized, "-1" otherwise. */ static int8_t i2s_compute_harmonized_frequencies(i2s_t *i2s_t_l, i2s_t *i2s_t_h, uint32_t *ptr_low_freq, uint32_t *ptr_high_freq, - float real_low_freq, float real_high_freq) + float real_low_freq, float real_high_freq) { - /* currently unused parameters */ - (void)i2s_t_h; - (void)ptr_high_freq; - /* Returning if the two real frequencies are already multiple one of the other. */ float division = real_high_freq / real_low_freq; float rest = (division - (uint32_t)division); @@ -879,29 +884,56 @@ if (rest == 0) { return 0; } + uint32_t multiplier = ((rest >= 0.5) ? ((uint32_t)division + 1) : (uint32_t)division); + + /* Get MCLK settings for both devices */ + bool low_freq_mclk = i2s_has_mclk(i2s_t_l); + bool high_freq_mclk = i2s_has_mclk(i2s_t_h); + + uint32_t new_low_freq_int = *ptr_low_freq; + uint32_t new_high_freq_int = *ptr_high_freq; /* Computing the harmonized frequencies so that they are multiple one of the other by a certain factor. */ - uint32_t multiplier = ((rest >= 0.5) ? ((uint32_t)division + 1) : (uint32_t)division); - - float new_low_freq = real_high_freq / multiplier; // NOTE/TODO: assuming MCLK always enabled (see `i2s_init()`)!!! - uint32_t new_low_freq_int_ceil = (uint32_t)ceilf(new_low_freq); - uint32_t new_low_freq_int_floor = (uint32_t)new_low_freq; + if(low_freq_mclk && !high_freq_mclk) { // start from low frequency + float new_high_freq = real_low_freq * multiplier; + uint32_t new_high_freq_int_ceil = (uint32_t)ceilf(new_high_freq); + uint32_t new_high_freq_int_floor = (uint32_t)new_high_freq; - uint32_t new_low_freq_int; - float real_new_low_freq = i2s_compute_closest_frequency(i2s_t_l, new_low_freq_int_floor); - if(real_new_low_freq == new_low_freq) { - new_low_freq_int = new_low_freq_int_floor; - } else { - real_new_low_freq = i2s_compute_closest_frequency(i2s_t_l, new_low_freq_int_ceil); - if(real_new_low_freq == new_low_freq) { + float real_new_high_freq = i2s_compute_closest_frequency(i2s_t_h, new_high_freq_int_ceil); + if(real_new_high_freq == new_high_freq) { + new_high_freq_int = new_high_freq_int_ceil; + } else { + real_new_high_freq = i2s_compute_closest_frequency(i2s_t_h, new_high_freq_int_floor); + if(real_new_high_freq == new_high_freq) { + new_high_freq_int = new_high_freq_int_floor; + } else { + return -1; // should never happen (assuming MCLK always enabled)! + } + } + } else { // start from high frequency + float new_low_freq = real_high_freq / multiplier; + uint32_t new_low_freq_int_ceil = (uint32_t)ceilf(new_low_freq); + uint32_t new_low_freq_int_floor = (uint32_t)new_low_freq; + + float real_new_low_freq = i2s_compute_closest_frequency(i2s_t_l, new_low_freq_int_floor); + if(real_new_low_freq == new_low_freq) { + new_low_freq_int = new_low_freq_int_floor; + } else { + real_new_low_freq = i2s_compute_closest_frequency(i2s_t_l, new_low_freq_int_ceil); + if(real_new_low_freq == new_low_freq) { new_low_freq_int = new_low_freq_int_ceil; - } else { - return -1; // should never happen (assuming MCLK always enabled)! - } + } else { + return -1; /* might happen for both devices with MCLK disabled & + higher frequency 16-bit wide and lower frequency 32-bit wide + and odd multiplier! + */ + } + } } *ptr_low_freq = new_low_freq_int; + *ptr_high_freq = new_high_freq_int; return 0; }