Il y avait des problèmes dans la libraire...

Dependents:   X_NUCLEO_CCA02M1

Fork of ST_I2S by ST

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;
 }