fix gsm0808_sc_cfg <-> gsm48_mr_cfg conversion

Deprecate
 gsm0808_sc_cfg_from_gsm48_mr_cfg() and
 gsm48_mr_cfg_from_gsm0808_sc_cfg(),
and add new functions
 gsm0808_sc_cfg_from_amr_modes() and
 gsm0808_sc_cfg_get_best_amr_modes()
to fix the behavior as follows:

When the mr_cfg enables a specific rate, do not include all AMR
configurations that feature this rate. Instead, enable only those
configurations that are a subset of the mr_cfg.
For example, in the old functions, setting only m4_75 = 1 would result
in enabling all of S0, S8, S9, S10, S12, S14. S14 would allow all of
4.75k, 5.9k, 7.95k, 12.2k, instead of limiting to 4.75k only.

In the new functions, do not modify the .version and .icmi members, act
only on the AMR rates.

Changes from old behavior to new behavior is clearly shown in
tests/gsm0808/gsm0808_test.ok.

Keep the deprecated functions unchanged, yielding incorrect behavior,
and let the API users decide when and how to upgrade to the more sane
behavior.
For example, changing the behavior of existing functions in-place would
have repercussions on osmo-bsc installations, where now only those AMR
modes listed in the config would be used -- we are becoming stricter.
Possibly this would deteriorate or break sites alone from upgrading
libosmocore -- i.e. those sites that fail to list an essential AMR rate
for matching with peers, but where that essential AMR rate was
erratically allowed by the old behavior.

The old behavior, by example of osmo-bsc:
- Picking rates in osmo-bsc.cfg has non-obvious effects, often
  including rates that are configured as 'forbidden'.
- If any of 4.75, 5.90, 7.40, 12.2 is enabled in osmo-bsc.cfg, the
  configuration S1 ends up enabled in s15_s0
  (gsm0808_sc_cfg_from_gsm48_mr_cfg()).
- In gsm48_mr_cfg_from_gsm0808_sc_cfg() used during channel activation,
  if S1 is present, the four rates from S1 are returned.
- In summary, in the vast majority of cases, the S1 set will be used --
  even if only one of its AMR rates is originally present in mr_cfg.
- Configurations above S7 are ignored.

The new behavior, assuming osmo-bsc moved to the more sane
implementation introduced in this patch:
- Only one of the rate combinations defined by S0..S15 is going to be
  used.
  This is mainly because AMR rate selections are sent to the MSC and
  back from the MSC in the somewhat limited S0..S15 bit form.
  Enabling one or more of these combinations of rates in osmo-bsc.cfg
  makes sense:
  - 4.75, 5.90, 7.40, 12.2 (S1)
  - 4.75, 5.90 (S8)
  - 4.75, 5.90, 6.70 (S9)
  - 4.75, 5.90, 6.70, 7.40 (S10)
  - 4.75, 5.90, 6.70, 10.2 (S12)
  - 4.75, 5.90, 7.95, 12.2 (S14)
- e.g. if only 4.75 is enabled, only 4.75 is used (S0).
- e.g. in case of 6.70=allowed + 7.75=allowed + 10.2=allowed,
  we have to choose between "only 6.70", "only 7.75", "only 10.2".
  On FR we'd pick S6 = "only 10.2", because it is the highest rate.
  So osmo-bsc.cfg should rather choose rates exactly matching a specific
  Sn bit, e.g. all rates of S12, to obtain a flexible variety of AMR
  rates.

3GPP TS 48.008 3.2.2.103 'Speech Codec List' says to this:

 NOTE: One of these Codec Configurations, "Config-NB-Code 1" = S1, is
 recommended for TrFO [Transcoder Free Operation].

S14 also seems a good choice, it is like S1 but with 7k95 instead of
7k40; 7k95 is the highest possible AMR-HR rate. It is not clear at this
point why S1 seems to be preferred over S14.

Ironically, the old behavior would usually end up selecting exactly S1
in almost every case, which is what 3GPP TS 48.008 3.2.2.103 recommends.
This is, however, not obvious to the caller / the site admin.

Related: SYS#5066
Change-Id: I900fda192742fa8f6dd54e9131ef1704b14cc41a
This commit is contained in:
Neels Hofmeyr 2022-09-06 04:55:39 +02:00
parent a41bd22349
commit d2d44883ac
7 changed files with 211 additions and 170 deletions

View File

@ -7,4 +7,6 @@
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
libosmogsm new header osmocom/gsm/protocol/gsm_44_060.h
libosmogsm new header osmocom/gsm/protocol/gsm_44_060.h
libosmogsm gsm0808_sc_cfg_from_gsm48_mr_cfg() Deprecate; replacement is gsm0808_sc_cfg_from_amr_modes().
libosmogsm gsm48_mr_cfg_from_gsm0808_sc_cfg() Deprecate; replacement is gsm0808_sc_cfg_get_best_amr_modes().

View File

@ -149,8 +149,15 @@ int gsm0808_dec_cell_id(struct gsm0808_cell_id *ci, const uint8_t *elem, uint8_t
int gsm0808_chan_type_to_speech_codec(uint8_t perm_spch);
int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc,
uint8_t perm_spch);
uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cfg, bool fr);
int gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t s15_s0);
uint16_t gsm0808_sc_cfg_from_amr_modes(uint8_t modes, bool full_rate);
uint8_t gsm0808_sc_cfg_get_all_amr_modes(uint16_t s15_s0, bool full_rate);
uint8_t gsm0808_sc_cfg_get_best_amr_modes(uint16_t s15_s0, bool full_rate);
uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cfg, bool fr)
OSMO_DEPRECATED("use gsm0808_sc_cfg_from_amr_modes() with fixed behavior");
int gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t s15_s0)
OSMO_DEPRECATED("use gsm0808_sc_cfg_get_best_amr_modes() or gsm0808_sc_cfg_get_all_amr_modes()");
/*! \returns 3GPP TS 08.08 §3.2.2.5 Class of a given Cause */
static inline enum gsm0808_cause_class gsm0808_cause_class(enum gsm0808_cause cause)

View File

@ -622,6 +622,16 @@ struct gsm48_multi_rate_conf {
#endif
} __attribute__((packed));
static inline uint8_t gsm48_multi_rate_conf_get_amr_modes(const struct gsm48_multi_rate_conf *cfg)
{
return ((uint8_t *)cfg)[1];
}
static inline void gsm48_multi_rate_conf_set_amr_modes(struct gsm48_multi_rate_conf *cfg, uint8_t modes)
{
((uint8_t *)cfg)[1] = modes;
}
/* Chapter 10.5.2.28(a) */
struct gsm48_power_cmd {
#if OSMO_IS_LITTLE_ENDIAN

View File

@ -1657,8 +1657,104 @@ int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc,
return 0;
}
/*! Determine a set of AMR speech codec configuration bits (S0-S15) from a
* given GSM 04.08 AMR configuration struct.
/*! Determine a set of AMR speech codec configuration bits (S0-S15) from a given set of AMR modes.
* Enable each of the S0..S15 bits that is a subset of the given modes.
* In other words, there must be no S0..S15 bit enabled that includes a mode that is disabled in modes.
* See 3GPP TS 28.062 Table 7.11.3.1.3-2, where each column defines one of the S0..S15 bits.
* The bits in 'modes' are a binary match for the mX_XX flags in struct gsm48_multi_rate_conf.mX_XX.
*
* Example:
* uint8_t modes = gsm48_multi_rate_conf_get_amr_modes(my_cfg);
* uint16_t s15_s0 = gsm0808_sc_cfg_from_amr_modes(modes, full_rate);
*
* \param[in] modes Set of modes, bitmask of (1 << GSM0808_AMR_MODE_4_75) | (1 << GSM0808_AMR_MODE_5_90) | ...
* \param[in] full_rate When false, apply special HR AMR exceptions.
* \returns configuration bits (S0-S15) */
uint16_t gsm0808_sc_cfg_from_amr_modes(uint8_t modes, bool full_rate)
{
uint16_t s15_s0 = 0;
int s_bit;
for (s_bit = 0; s_bit < 16; s_bit++) {
uint8_t s_modes = gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][s_bit];
/* When s_modes is a non-zero subset of the input modes, add this configuration to s15_s0.
* Some Sn are empty, because they are not supported for HR, or not at all in GSM. */
if (s_modes && ((s_modes & modes) == s_modes))
s15_s0 |= (1 << s_bit);
}
return s15_s0;
}
/*! Return all AMR modes present in any of the given s15_s0 configurations.
* The returned bits are a binary match for the mX_XX flags in struct gsm48_multi_rate_conf.mX_XX.
*
* Example:
* uint8_t modes = gsm0808_sc_cfg_get_all_amr_modes(s15_s0, full_rate);
* gsm48_multi_rate_conf_set_amr_modes(&my_cfg, modes);
*
* \param[in] s15_s0 S15-S0 configuration bits, see gsm0808_amr_modes_from_cfg.
* \param[in] full_rate When false, return only modes compatible with HR AMR, and only observe Sn bits marked as
* supported by HR AMR, as in gsm0808_amr_modes_from_cfg.
* \return Bitmask of modes present in s15_s0, as in (1 << GSM0808_AMR_MODE_X_XX).
*/
uint8_t gsm0808_sc_cfg_get_all_amr_modes(uint16_t s15_s0, bool full_rate)
{
uint8_t modes = 0;
int s_bit;
for (s_bit = 0; s_bit < 16; s_bit++) {
if (!(s15_s0 & (1 << s_bit)))
continue;
modes |= gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][s_bit];
}
return modes;
}
/*! Return "the best choice" of at most four AMR modes present in the given s15_s0 configurations.
* This is useful to determine which four or less modes to send in the MR CFG IE during GSM channel activation.
*
* "The best choice": return the modes for the highest Sn present in s15_s0, with these exceptions:
* - Skip any Sn that is not supported; e.g. HR does not support S6, and GSM never supports S11. See API doc of
* gsm0808_amr_modes_from_cfg for an explanation.
* - S1 ranks higher than S2..S9 -- S1 has a more favorable variety of rates than the latter ones.
*
* For example:
* - if S8 and S9 are set, return the modes for S9.
* - if S0 thru S9 are set, return the modes for S1 (because S1 ranks higher than S9).
* - if S0 thru S11 are set, return the modes for S10 (because S11 is not supported).
*
* Code example:
* uint8_t modes = gsm0808_sc_cfg_get_best_amr_modes(s15_s0, full_rate);
* gsm48_multi_rate_conf_set_amr_modes(&my_cfg, modes);
*
* \param[in] s15_s0 S15-S0 configuration bits, see gsm0808_amr_modes_from_cfg.
* \param[in] full_rate When false, return only modes compatible with HR AMR, and only observe Sn bits marked as
* supported by HR AMR, as in gsm0808_amr_modes_from_cfg.
* \return Bitmask of modes chosen from s15_s0, as in (1 << GSM0808_AMR_MODE_X_XX) | (1 << ...), or 0 if no modes are
* viable.
*/
uint8_t gsm0808_sc_cfg_get_best_amr_modes(uint16_t s15_s0, bool full_rate)
{
/* Could skip S15, S13, S11 here, but let's rather rely on the definition of gsm0808_amr_modes_from_cfg. */
const int s_bit_preference[] = { 15, 14, 13, 12, 11, 10, 1, 9, 8, 7, 6, 5, 4, 3, 2, 0 };
int i;
uint8_t modes = 0;
for (i = 0; (!modes) && (i < ARRAY_SIZE(s_bit_preference)); i++) {
int s_bit = s_bit_preference[i];
if (!(s15_s0 & s_bit))
continue;
modes = gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][s_bit];
}
return modes;
}
/*! Deprecated, use gsm0808_sc_cfg_from_amr_modes(); The following code is an equivalent replacement for a call to
* s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, fr):
*
* s15_s0 = gsm0808_sc_cfg_from_amr_modes(gsm48_multi_rate_conf_get_amr_modes(cfg), fr);
*
* Determine a set of AMR speech codec configuration bits (S0-S15) from a given GSM 04.08 AMR configuration struct.
* Enable all those AMR configurations where at least one of its AMR rates is enabled in cfg.
* This is usually undesired behavior, use gsm0808_sc_cfg_from_amr_modes() instead.
* \param[in] cfg AMR configuration in GSM 04.08 format.
* \param[in] hint if the resulting configuration shall be used with a FR or HR TCH.
* \returns configuration bits (S0-S15) */
@ -1710,7 +1806,13 @@ uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cf
return s15_s0;
}
/*! Determine a GSM 04.08 AMR configuration struct from a set of speech codec
/*! Deprecated, use gsm0808_sc_cfg_get_best_amr_modes(); The following code is an equivalent replacement for a call to
* gsm48_mr_cfg_from_gsm0808_sc_cfg(cfg, s15_s0):
*
* *cfg = (struct gsm48_multi_rate_conf){ .ver = 1, .icmi = 1 };
* gsm48_multi_rate_conf_set_amr_modes(cfg, gsm0808_sc_cfg_get_best_amr_modes(s15_s0, true));
*
* Determine a GSM 04.08 AMR configuration struct from a set of speech codec
* configuration bits (S0-S15)
* \param[out] cfg AMR configuration in GSM 04.08 format.
* \param[in] s15_s0 configuration bits (S15-S0, non-ambiguous).

View File

@ -250,6 +250,9 @@ gsm0808_cell_ids_match;
gsm0808_cell_id_matches_list;
gsm0808_chan_type_to_speech_codec;
gsm0808_speech_codec_from_chan_type;
gsm0808_sc_cfg_from_amr_modes;
gsm0808_sc_cfg_get_all_amr_modes;
gsm0808_sc_cfg_get_best_amr_modes;
gsm0808_sc_cfg_from_gsm48_mr_cfg;
gsm48_mr_cfg_from_gsm0808_sc_cfg;
gsm0808_amr_modes_from_cfg;

View File

@ -2094,11 +2094,11 @@ static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate
printf("Input:\n");
print_mr_cfg(cfg);
s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true);
s15_s0 = gsm0808_sc_cfg_from_amr_modes(gsm48_multi_rate_conf_get_amr_modes(cfg), true);
printf("Result (fr):\n");
print_s15_s0(s15_s0, true);
s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false);
s15_s0 = gsm0808_sc_cfg_from_amr_modes(gsm48_multi_rate_conf_get_amr_modes(cfg), false);
printf("Result (hr):\n");
print_s15_s0(s15_s0, false);
@ -2109,7 +2109,7 @@ static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void)
{
struct gsm48_multi_rate_conf cfg;
printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n");
printf("Testing gsm0808_sc_cfg_from_amr_modes():\n");
memset(&cfg, 0, sizeof(cfg));
@ -2297,26 +2297,22 @@ static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void)
static void test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(uint16_t s15_s0)
{
struct gsm48_multi_rate_conf cfg;
int rc;
struct gsm48_multi_rate_conf cfg = {};
printf("Input:\n");
print_s15_s0(s15_s0, true);
rc = gsm48_mr_cfg_from_gsm0808_sc_cfg(&cfg, s15_s0);
gsm48_multi_rate_conf_set_amr_modes(&cfg, gsm0808_sc_cfg_get_best_amr_modes(s15_s0, true));
printf("Output:\n");
print_mr_cfg(&cfg);
if (rc != 0)
printf(" Result invalid!\n");
printf("\n");
}
void test_gsm48_mr_cfg_from_gsm0808_sc_cfg(void)
{
printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n");
printf("Testing gsm0808_sc_cfg_get_best_amr_modes():\n");
/* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
* (up to four codecs may become selected) */

View File

@ -85,7 +85,7 @@ test_gsm0808_enc_dec_cell_id_lai_and_lac: encoded: 05 06 04 21 63 54 23 42 (rc =
test_gsm0808_enc_dec_cell_id_ci: encoded: 05 03 02 04 23 (rc = 5)
test_gsm0808_enc_dec_cell_id_lac_and_ci: encoded: 05 05 01 04 23 02 35 (rc = 7)
test_gsm0808_enc_dec_cell_id_global: encoded: 05 08 00 21 63 54 23 42 04 23 (rc = 10)
Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():
Testing gsm0808_sc_cfg_from_amr_modes():
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
@ -98,19 +98,11 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- ------- ------- ------- ------- ------- -------
Result (fr):
S15-S0 = 0x5701 = 0b0101011100000001
S15-S0 = 0x0001 = 0b0000000000000001
S0 4.75
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0701 = 0b0000011100000001
S15-S0 = 0x0001 = 0b0000000000000001
S0 4.75
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
@ -124,54 +116,38 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- m5_90=1 ------- ------- ------- ------- -------
Result (fr):
S15-S0 = 0x5704 = 0b0101011100000100
S15-S0 = 0x0004 = 0b0000000000000100
S2 5.90
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0704 = 0b0000011100000100
S15-S0 = 0x0004 = 0b0000000000000100
S2 5.90
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- m6_70=1 ------- ------- ------- -------
Result (fr):
S15-S0 = 0x1608 = 0b0001011000001000
S15-S0 = 0x0008 = 0b0000000000001000
S3 6.70
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
Result (hr):
S15-S0 = 0x0608 = 0b0000011000001000
S15-S0 = 0x0008 = 0b0000000000001000
S3 6.70
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- m7_40=1 ------- ------- -------
Result (fr):
S15-S0 = 0x0410 = 0b0000010000010000
S15-S0 = 0x0010 = 0b0000000000010000
S4 7.40
S10 4.75 5.90 6.70 7.40
Result (hr):
S15-S0 = 0x0410 = 0b0000010000010000
S15-S0 = 0x0010 = 0b0000000000010000
S4 7.40
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- m7_95=1 ------- -------
Result (fr):
S15-S0 = 0x4020 = 0b0100000000100000
S15-S0 = 0x0020 = 0b0000000000100000
S5 7.95
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0020 = 0b0000000000100000
S5 7.95
@ -180,9 +156,8 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- m10_2=1 -------
Result (fr):
S15-S0 = 0x1040 = 0b0001000001000000
S15-S0 = 0x0040 = 0b0000000001000000
S6 10.2
S12 4.75 5.90 6.70 10.2
Result (hr):
S15-S0 = 0x0000 = 0b0000000000000000
@ -190,9 +165,8 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- m12_2=1
Result (fr):
S15-S0 = 0x4080 = 0b0100000010000000
S15-S0 = 0x0080 = 0b0000000010000000
S7 12.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0000 = 0b0000000000000000
@ -200,128 +174,92 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 m5_15=1 m5_90=1 m6_70=1 ------- ------- ------- -------
Result (fr):
S15-S0 = 0x570d = 0b0101011100001101
S15-S0 = 0x030d = 0b0000001100001101
S0 4.75
S2 5.90
S3 6.70
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x070d = 0b0000011100001101
S15-S0 = 0x030d = 0b0000001100001101
S0 4.75
S2 5.90
S3 6.70
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- m7_40=1 m7_95=1 m10_2=1 m12_2=1
Result (fr):
S15-S0 = 0x54f0 = 0b0101010011110000
S15-S0 = 0x00f0 = 0b0000000011110000
S4 7.40
S5 7.95
S6 10.2
S7 12.2
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0430 = 0b0000010000110000
S15-S0 = 0x0030 = 0b0000000000110000
S4 7.40
S5 7.95
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- m5_90=1 m6_70=1 ------- ------- m10_2=1 m12_2=1
Result (fr):
S15-S0 = 0x57cc = 0b0101011111001100
S15-S0 = 0x00cc = 0b0000000011001100
S2 5.90
S3 6.70
S6 10.2
S7 12.2
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x070c = 0b0000011100001100
S15-S0 = 0x000c = 0b0000000000001100
S2 5.90
S3 6.70
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 m5_15=1 ------- ------- m7_40=1 m7_95=1 ------- -------
Result (fr):
S15-S0 = 0x5731 = 0b0101011100110001
S15-S0 = 0x0031 = 0b0000000000110001
S0 4.75
S4 7.40
S5 7.95
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0731 = 0b0000011100110001
S15-S0 = 0x0031 = 0b0000000000110001
S0 4.75
S4 7.40
S5 7.95
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- m5_15=1 ------- m6_70=1 ------- m7_95=1 ------- m12_2=1
Result (fr):
S15-S0 = 0x56a8 = 0b0101011010101000
S15-S0 = 0x00a8 = 0b0000000010101000
S3 6.70
S5 7.95
S7 12.2
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0628 = 0b0000011000101000
S15-S0 = 0x0028 = 0b0000000000101000
S3 6.70
S5 7.95
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- m10_2=1 -------
Result (fr):
S15-S0 = 0x5755 = 0b0101011101010101
S15-S0 = 0x0155 = 0b0000000101010101
S0 4.75
S2 5.90
S4 7.40
S6 10.2
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0717 = 0b0000011100010111
S15-S0 = 0x0117 = 0b0000000100010111
S0 4.75
S1 4.75 5.90 7.40
S2 5.90
S4 7.40
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
@ -357,51 +295,39 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
Result (fr):
S15-S0 = 0x5797 = 0b0101011110010111
S15-S0 = 0x0197 = 0b0000000110010111
S0 4.75
S1 4.75 5.90 7.40 12.2
S2 5.90
S4 7.40
S7 12.2
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0717 = 0b0000011100010111
S15-S0 = 0x0117 = 0b0000000100010111
S0 4.75
S1 4.75 5.90 7.40
S2 5.90
S4 7.40
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- -------
Result (fr):
S15-S0 = 0x5715 = 0b0101011100010101
S15-S0 = 0x0115 = 0b0000000100010101
S0 4.75
S2 5.90
S4 7.40
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
S12 4.75 5.90 6.70 10.2
S14 4.75 5.90 7.95 12.2
Result (hr):
S15-S0 = 0x0717 = 0b0000011100010111
S15-S0 = 0x0117 = 0b0000000100010111
S0 4.75
S1 4.75 5.90 7.40
S2 5.90
S4 7.40
S8 4.75 5.90
S9 4.75 5.90 6.70
S10 4.75 5.90 6.70 7.40
Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():
Testing gsm0808_sc_cfg_get_best_amr_modes():
Input:
S15-S0 = 0xff03 = 0b1111111100000011
S0 4.75
@ -415,15 +341,14 @@ Input:
S14 4.75 5.90 7.95 12.2
S15 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0000 = 0b0000000000000000
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Result invalid!
Input:
S15-S0 = 0xff06 = 0b1111111100000110
@ -438,8 +363,8 @@ Input:
S14 4.75 5.90 7.95 12.2
S15 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x3e08 = 0b0011111000001000
@ -450,8 +375,8 @@ Input:
S12 4.75 5.90 6.70 10.2
S13 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- m6_70=1 ------- ------- ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0c12 = 0b0000110000010010
@ -460,8 +385,8 @@ Input:
S10 4.75 5.90 6.70 7.40
S11 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0xc020 = 0b1100000000100000
@ -469,8 +394,8 @@ Input:
S14 4.75 5.90 7.95 12.2
S15 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- ------- ------- m7_95=1 ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Input:
S15-S0 = 0x3040 = 0b0011000001000000
@ -478,8 +403,8 @@ Input:
S12 4.75 5.90 6.70 10.2
S13 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- ------- ------- ------- m10_2=1 -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Input:
S15-S0 = 0xc082 = 0b1100000010000010
@ -488,64 +413,64 @@ Input:
S14 4.75 5.90 7.95 12.2
S15 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0001 = 0b0000000000000001
S0 4.75
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- ------- ------- ------- ------- ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
Input:
S15-S0 = 0x0002 = 0b0000000000000010
S1 4.75 5.90 7.40 12.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0004 = 0b0000000000000100
S2 5.90
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- m5_90=1 ------- ------- ------- ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0008 = 0b0000000000001000
S3 6.70
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- m6_70=1 ------- ------- ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0010 = 0b0000000000010000
S4 7.40
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- ------- m7_40=1 ------- ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Input:
S15-S0 = 0x0020 = 0b0000000000100000
S5 7.95
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- ------- ------- m7_95=1 ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Input:
S15-S0 = 0x0040 = 0b0000000001000000
S6 10.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- ------- ------- ------- m10_2=1 -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Input:
S15-S0 = 0x0080 = 0b0000000010000000
S7 12.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- ------- ------- ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Input:
S15-S0 = 0x0058 = 0b0000000001011000
@ -553,24 +478,24 @@ Input:
S4 7.40
S6 10.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- ------- m6_70=1 m7_40=1 ------- m10_2=1 -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0021 = 0b0000000000100001
S0 4.75
S5 7.95
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- ------- ------- ------- m7_95=1 ------- -------
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
Input:
S15-S0 = 0x0084 = 0b0000000010000100
S2 5.90
S7 12.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
------- ------- m5_90=1 ------- ------- ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0086 = 0b0000000010000110
@ -578,17 +503,16 @@ Input:
S2 5.90
S7 12.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x000a = 0b0000000000001010
S1 4.75 5.90 7.40 12.2
S3 6.70
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
Result invalid!
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0079 = 0b0000000001111001
@ -598,16 +522,14 @@ Input:
S5 7.95
S6 10.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- ------- m6_70=1 m7_40=1 m7_95=1 ------- -------
Result invalid!
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
Input:
S15-S0 = 0x0000 = 0b0000000000000000
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
------- ------- ------- ------- ------- ------- ------- -------
Result invalid!
Input:
S15-S0 = 0xffff = 0b1111111111111111
@ -628,9 +550,8 @@ Input:
S14 4.75 5.90 7.95 12.2
S15 (empty)
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=1 ------- m5_90=1 ------- m7_40=1 ------- ------- m12_2=1
Result invalid!
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 ------- m5_90=1 ------- ------- m7_95=1 ------- m12_2=1
test_cell_id_matching