neels has submitted this change. ( 
https://gerrit.osmocom.org/c/libosmocore/+/29473 )

Change subject: add gsm0808_amr_modes_from_cfg
......................................................................

add gsm0808_amr_modes_from_cfg

Provide the definitions from 3GPP TS 28.062, Table 7.11.3.1.3-2 as
generally usable API.

Likely users:
- upcoming patch to improve conversion between S0-S15 and MultiRate
  config, I900fda192742fa8f6dd54e9131ef1704b14cc41a
- osmo-msc to figure out conversion between SDP AMR mode-set and 3GPP TS
  48.008 Permitted Speech S0-S15.
- osmo-bsc to choose AMR modes for channel activation from cfg /
  permitted speech from MSC.

Related: SYS#5066
Change-Id: Icef7dd626d3d4641c66b8dd87e2047fc0ab547d1
---
M include/osmocom/gsm/protocol/gsm_08_08.h
M src/gsm/gsm0808.c
M src/gsm/libosmogsm.map
3 files changed, 143 insertions(+), 0 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified




diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h 
b/include/osmocom/gsm/protocol/gsm_08_08.h
index 5060915..88ac610 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -687,6 +687,29 @@
        GSM0808_SC_CFG_AMR_12_2 = 0x0080,
 };

+/* Bit index of a mode as returned by gsm0808_amr_modes_from_cfg[].
+ * Example:
+ *   if (gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][9] & 
GSM0808_AMR_MODE_4_75)
+ *       printf("S9 supports 4k75");
+ */
+enum gsm0808_amr_mode {
+       GSM0808_AMR_MODE_4_75 = 0,
+       GSM0808_AMR_MODE_5_15,
+       GSM0808_AMR_MODE_5_90,
+       GSM0808_AMR_MODE_6_70,
+       GSM0808_AMR_MODE_7_40,
+       GSM0808_AMR_MODE_7_95,
+       GSM0808_AMR_MODE_10_2,
+       GSM0808_AMR_MODE_12_2,
+};
+extern const struct value_string gsm0808_amr_mode_names[];
+static inline const char *gsm0808_amr_mode_name(enum gsm0808_amr_mode val)
+{
+       return get_value_string(gsm0808_amr_mode_names, val);
+}
+
+extern const uint8_t gsm0808_amr_modes_from_cfg[2][16];
+
 /* 3GPP TS 48.008 3.2.2.103 Speech Codec List */
 #define SPEECH_CODEC_MAXLEN 255
 struct gsm0808_speech_codec_list {
diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c
index ec4c39b..e1768c1 100644
--- a/src/gsm/gsm0808.c
+++ b/src/gsm/gsm0808.c
@@ -2028,4 +2028,101 @@
        { 0, NULL }
 };

+/* Convert one S0-S15 bit to its set of AMR modes, for HR AMR and FR AMR.
+ * This is 3GPP TS 28.062 Table 7.11.3.1.3-2: "Preferred Configurations", with 
some configurations removed as specified
+ * in 3GPP TS 48.008 3.2.2.103:
+ *
+ *  FR_AMR is coded ‘0011’.
+ *  S11, S13 and S15 are reserved and coded with zeroes.
+ *
+ *  HR_AMR is coded ‘0100’.
+ *  S6 - S7 and S11 – S15 are reserved and coded with zeroes.
+ *
+ * Meaning: for FR, exclude all Optimisation Mode configurations.
+ * For HR, exclude all that are not supported by HR AMR -- drop all that 
include at least one of
+ * 10.2 or 12.2.
+ *
+ * Also, for HR, drop 12.2k from S1.
+ *
+ * The first array dimension is 0 for half rate and 1 for full rate.
+ * The second array dimension is the configuration number (0..15) aka Sn.
+ * The values are bitmask combinations of (1 << GSM0808_AMR_MODE_nnnn).
+ *
+ * For example, accumulate all modes that are possible in a given my_s15_s0:
+ *
+ *   uint8_t modes = 0;
+ *   for (s_bit = 0; s_bit < 15; s_bit++)
+ *       if (my_s15_s0 & (1 << s_bit))
+ *           modes |= gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][s_bit];
+ *   for (i = 0; i < 8; i++)
+ *       if (modes & (1 << i))
+ *           printf(" %s", gsm0808_amr_mode_name(i));
+ */
+const uint8_t gsm0808_amr_modes_from_cfg[2][16] = {
+#define B(X) (1 << (GSM0808_AMR_MODE_##X))
+       /* HR */
+       {
+               /* Sn = modes */
+                [0] = B(4_75),
+                [1] = B(4_75)         | B(5_90)           | B(7_40),
+                [2] = B(5_90),
+                [3] = B(6_70),
+                [4] = B(7_40),
+                [5] = B(7_95),
+                [6] = 0,
+                [7] = 0,
+
+                [8] = B(4_75)         | B(5_90),
+                [9] = B(4_75)         | B(5_90) | B(6_70),
+               [10] = B(4_75)         | B(5_90) | B(6_70) | B(7_40),
+               [11] = 0,
+               [12] = 0,
+               [13] = 0,
+               [14] = 0,
+               [15] = 0,
+       },
+       /* FR */
+       {
+               /* Sn = modes */
+                [0] = B(4_75),
+                [1] = B(4_75)         | B(5_90)           | B(7_40)            
         | B(12_2),
+                [2] = B(5_90),
+                [3] = B(6_70),
+                [4] = B(7_40),
+                [5] = B(7_95),
+                [6] = B(10_2),
+                [7] = B(12_2),
+
+                [8] = B(4_75)         | B(5_90),
+                [9] = B(4_75)         | B(5_90) | B(6_70),
+               [10] = B(4_75)         | B(5_90) | B(6_70) | B(7_40),
+               [11] = 0,
+               [12] = B(4_75)         | B(5_90) | B(6_70)                     
| B(10_2),
+               [13] = 0,
+               [14] = B(4_75)         | B(5_90)                     | B(7_95)  
         | B(12_2),
+               [15] = 0,
+       }
+};
+
+/* AMR mode names from GSM0808_AMR_MODE_*, for use with 
gsm0808_amr_modes_from_cfg.
+ *
+ * For example:
+ *   printf("S9: ");
+ *   uint8_t s9_modes = gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][9];
+ *   for (bit = 0; bit < 8; bit++)
+ *       if (s9_modes & (1 << bit))
+ *           printf("%s,", gsm0808_amr_mode_name(bit));
+ */
+const struct value_string gsm0808_amr_mode_names[] = {
+       { GSM0808_AMR_MODE_4_75, "4.75" },
+       { GSM0808_AMR_MODE_5_15, "5.15" },
+       { GSM0808_AMR_MODE_5_90, "5.90" },
+       { GSM0808_AMR_MODE_6_70, "6.70" },
+       { GSM0808_AMR_MODE_7_40, "7.40" },
+       { GSM0808_AMR_MODE_7_95, "7.95" },
+       { GSM0808_AMR_MODE_10_2, "10.2" },
+       { GSM0808_AMR_MODE_12_2, "12.2" },
+       {}
+};
+
 /*! @} */
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 21f8e15..6ad363f 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -252,6 +252,8 @@
 gsm0808_speech_codec_from_chan_type;
 gsm0808_sc_cfg_from_gsm48_mr_cfg;
 gsm48_mr_cfg_from_gsm0808_sc_cfg;
+gsm0808_amr_modes_from_cfg;
+gsm0808_amr_mode_names;
 gsm0808_speech_codec_type_names;
 gsm0808_permitted_speech_names;
 gsm0808_chosen_enc_alg_names;

--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/29473
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Icef7dd626d3d4641c66b8dd87e2047fc0ab547d1
Gerrit-Change-Number: 29473
Gerrit-PatchSet: 4
Gerrit-Owner: neels <nhofm...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pma...@sysmocom.de>
Gerrit-Reviewer: laforge <lafo...@osmocom.org>
Gerrit-Reviewer: neels <nhofm...@sysmocom.de>
Gerrit-Reviewer: pespin <pes...@sysmocom.de>
Gerrit-MessageType: merged

Reply via email to