You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2020/09/28 12:34:27 UTC

[mynewt-core] branch master updated: hw/drivers/i2s: Add support for 24 bits samples for NRF52

This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new dc92f19  hw/drivers/i2s: Add support for 24 bits samples for NRF52
dc92f19 is described below

commit dc92f1986a0c18a5158917e695174d343c2be658
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue Sep 22 11:50:54 2020 +0200

    hw/drivers/i2s: Add support for 24 bits samples for NRF52
    
    I2S setup was no done for 24 bits samples, all calculations were
    for 16 and 8 bits samples only.
    
    Ratio value for 48000Hz sample rate was incorrect and would result
    in an assert in nrfx code.
---
 hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c | 70 ++++++++++++++++++++++----------
 1 file changed, 49 insertions(+), 21 deletions(-)

diff --git a/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c b/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c
index ea39f81..fc73b81 100644
--- a/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c
+++ b/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c
@@ -167,31 +167,59 @@ i2s_driver_stop(struct i2s *i2s)
     return 0;
 }
 
+/* Settings are stored for following sampling frequencies:
+ * 8000, 16000, 22050, 32000, 441000, 48000 */
+struct i2s_clock_cfg {
+    nrf_i2s_mck_t mck_setup;
+    nrf_i2s_ratio_t ratio;
+};
+
+static const uint16_t sample_rates[] = { 8000, 16000, 22050, 32000, 44100, 48000 };
+
+static const struct i2s_clock_cfg mck_for_8_16_bit_samples[] = {
+    { NRF_I2S_MCK_32MDIV125, NRF_I2S_RATIO_32X}, /*  8000:  8000     LRCK error  0.0% */
+    { NRF_I2S_MCK_32MDIV63, NRF_I2S_RATIO_32X},  /* 16000: 15873.016 LRCK error -0.8% */
+    { NRF_I2S_MCK_32MDIV15, NRF_I2S_RATIO_96X},  /* 22050: 22222.222 LRCK error  0.8% */
+    { NRF_I2S_MCK_32MDIV31, NRF_I2S_RATIO_32X},  /* 32000: 32258.065 LRCK error  0.8% */
+    { NRF_I2S_MCK_32MDIV23, NRF_I2S_RATIO_32X},  /* 44100: 43478.261 LRCK error -1.4% */
+    { NRF_I2S_MCK_32MDIV21, NRF_I2S_RATIO_32X}   /* 48000: 47619.048 LRCK error -0.8% */
+};
+
+static const struct i2s_clock_cfg mck_for_24_bit_samples[] = {
+    { NRF_I2S_MCK_32MDIV21, NRF_I2S_RATIO_192X}, /*  8000:  7936.508 LRCK error -0.8% */
+    { NRF_I2S_MCK_32MDIV42, NRF_I2S_RATIO_48X},  /* 16000: 15873.016 LRCK error -0.8% */
+    { NRF_I2S_MCK_32MDIV30, NRF_I2S_RATIO_48X},  /* 22050: 22222.222 LRCK error  0.8% */
+    { NRF_I2S_MCK_32MDIV21, NRF_I2S_RATIO_48X},  /* 32000: 31746.032 LRCK error -0.8% */
+    { NRF_I2S_MCK_32MDIV15, NRF_I2S_RATIO_48X},  /* 44100: 44444.444 LRCK error  0.8% */
+    { NRF_I2S_MCK_32MDIV15, NRF_I2S_RATIO_48X}   /* 48000: 44444.444 LRCK error -7.4% */
+};
+
 static void
 nrf52_select_i2s_clock_cfg(nrfx_i2s_config_t *cfg, uint32_t sample_rate)
 {
-    cfg->ratio = NRF_I2S_RATIO_32X;
-    switch (sample_rate) {
-    case 16000:
-        cfg->mck_setup = NRF_I2S_MCK_32MDIV63;
-        break;
-    case 22500:
-        cfg->mck_setup = NRF_I2S_MCK_32MDIV42;
-        break;
-    case 32000:
-        cfg->mck_setup = NRF_I2S_MCK_32MDIV31;
-        break;
-    case 441000:
-        cfg->mck_setup = NRF_I2S_MCK_32MDIV23;
-        break;
-    case 48000:
-        cfg->ratio = NRF_I2S_RATIO_48X;
-        cfg->mck_setup = NRF_I2S_MCK_32MDIV21;
-        break;
-    default:
-        assert(0);
-        cfg->mck_setup = NRF_I2S_MCK_32MDIV63;
+    int i;
+
+    if (cfg->ratio != 0 || cfg->mck_setup != 0) {
+        /* User provided custom clock setup, no need to use stock values */
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(sample_rates); ++i) {
+        if (sample_rates[i] == sample_rate) {
+            if (cfg->sample_width == NRF_I2S_SWIDTH_8BIT ||
+                cfg->sample_width == NRF_I2S_SWIDTH_16BIT) {
+                cfg->ratio = mck_for_8_16_bit_samples[i].ratio;
+                cfg->mck_setup = mck_for_8_16_bit_samples[i].mck_setup;
+            } else if (cfg->sample_width == NRF_I2S_SWIDTH_24BIT) {
+                cfg->ratio = mck_for_24_bit_samples[i].ratio;
+                cfg->mck_setup = mck_for_24_bit_samples[i].mck_setup;
+            } else {
+                /* Invalid value of sample_width */
+                assert(0);
+            }
+            break;
+        }
     }
+    assert(cfg->mck_setup);
 }
 
 int