[RFC] fix gsm0808_sc_cfg <-> gsm48_mr_cfg conversion

This is a REQUEST FOR COMMENTS. I am fairly certain that the conversion
 between mr_cfg and gsm0808_sc needs fixing, but I do not feel
 sufficiently certain that what this patch does is the best choice.

Deprecate
 gsm0808_sc_cfg_from_gsm48_mr_cfg() and
 gsm48_mr_cfg_from_gsm0808_sc_cfg(),
and add new functions
 gsm0808_sc_cfg_from_modes() and
 gsm0808_sc_cfg_get_best_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.

Before this patch, for example, setting only m4_75 = true 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.

This change in behavior has potential repercussions on osmo-bsc
installations, where now only those AMR modes listed in the config will
be used -- we are becoming stricter. Possibly this deteriorates or
breaks sites from upgrading libosmocore alone -- 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 bug.

For that reason, keep the current gsm0808_sc_cfg_from_gsm48_mr_cfg()
unchanged, yielding incorrect behavior, and let the API users decide
when and how to fix this behavior.

The old behavior, by example of osmo-bsc:
- It is not possible to freely pick rates.
- Picking rates in osmo-bsc.cfg has non-obvious behavior, 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:
- It is not possible to freely pick rates.
- 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'll pick S6 = "only 10.2", because it is the highest rate.

Related: SYS#5066
Change-Id: I900fda192742fa8f6dd54e9131ef1704b14cc41a
This commit is contained in:
Neels Hofmeyr 2022-09-06 04:55:39 +02:00
parent 27243ced56
commit 24ec86496b
7 changed files with 201 additions and 168 deletions

View File

@ -7,3 +7,5 @@
# 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 gsm0808_sc_cfg_from_gsm48_mr_cfg() Deprecate; replacement is gsm0808_sc_cfg_from_modes().
libosmogsm gsm48_mr_cfg_from_gsm0808_sc_cfg() Deprecate; replacement is gsm0808_sc_cfg_get_best_modes().

View File

@ -144,8 +144,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_modes(uint8_t modes, bool full_rate);
uint8_t gsm0808_sc_cfg_get_all_modes(uint16_t s15_s0, bool full_rate);
uint8_t gsm0808_sc_cfg_get_best_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_gsm48_mr_cfg2() with fixed behavior");
int gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t s15_s0)
OSMO_DEPRECATED("use gsm48_mr_cfg_from_gsm0808_sc_cfg_all() or gsm48_mr_cfg_from_gsm0808_sc_cfg_four");
/*! \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_modes(const struct gsm48_multi_rate_conf *cfg)
{
return ((uint8_t *)cfg)[1];
}
static inline void gsm48_multi_rate_conf_set_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

@ -1588,8 +1588,96 @@ 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_modes(my_cfg);
* uint16_t s15_s0 = gsm0808_sc_cfg_from_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_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 cfg_modes, add this configuration to s15_s0. */
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_modes(s15_s0, full_rate);
* gsm48_multi_rate_conf_set_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_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 & 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 modes to send in the MR CFG IE during GSM channel activation.
*
* "The best choice": return the modes for the highest bit present in s15_s0 (that is supported / is non-empty), with
* the exception: favor S1 over S0, S2..S9 -- S1 has a more favorable variety of rates than the latter ones.
*
* Apply limitations of GSM, according to full_rate; see gsm0808_amr_modes_from_cfg for an explanation.
*
* Example:
* uint8_t modes = gsm0808_sc_cfg_get_four_modes(s15_s0, full_rate);
* gsm48_multi_rate_conf_set_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).
*/
uint8_t gsm0808_sc_cfg_get_best_modes(uint16_t s15_s0, bool full_rate)
{
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_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_modes(gsm48_multi_rate_conf_get_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_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) */
@ -1641,7 +1729,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_modes(); The following code is an equivalent replacement for a call to
* gsm0808_sc_cfg_get_best_modes(cfg, s15_s0):
*
* *cfg = (struct gsm48_multi_rate_conf){ .ver = 1, .icmi = 1 };
* gsm48_multi_rate_conf_set_modes(cfg, gsm0808_sc_cfg_get_best_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

@ -244,6 +244,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_modes;
gsm0808_sc_cfg_get_all_modes;
gsm0808_sc_cfg_get_best_modes;
gsm0808_sc_cfg_from_gsm48_mr_cfg;
gsm48_mr_cfg_from_gsm0808_sc_cfg;
gsm0808_amr_modes_from_cfg;

View File

@ -1940,11 +1940,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_modes(gsm48_multi_rate_conf_get_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_modes(gsm48_multi_rate_conf_get_modes(cfg), false);
printf("Result (hr):\n");
print_s15_s0(s15_s0, false);
@ -1955,7 +1955,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_modes():\n");
memset(&cfg, 0, sizeof(cfg));
@ -2144,25 +2144,21 @@ 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;
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_modes(&cfg, gsm0808_sc_cfg_get_best_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()
{
printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n");
printf("Testing gsm0808_sc_cfg_get_best_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_modes():
Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
@ -98,19 +98,11 @@ Input:
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=0
m4_75=1 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
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
m4_75=0 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
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
m4_75=0 m5_15=0 m5_90=0 m6_70=1 m7_40=0 m7_95=0 m10_2=0 m12_2=0
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
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=0
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
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=0
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
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=1 m12_2=0
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
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=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 m7_40=0 m7_95=0 m10_2=0 m12_2=0
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
m4_75=0 m5_15=0 m5_90=0 m6_70=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
m4_75=0 m5_15=0 m5_90=1 m6_70=1 m7_40=0 m7_95=0 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 m5_90=0 m6_70=0 m7_40=1 m7_95=1 m10_2=0 m12_2=0
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
m4_75=0 m5_15=1 m5_90=0 m6_70=1 m7_40=0 m7_95=1 m10_2=0 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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=1 m12_2=0
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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=0
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_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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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
m4_75=0 m5_15=0 m5_90=0 m6_70=1 m7_40=0 m7_95=0 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=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
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=1 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=1
Input:
S15-S0 = 0x0004 = 0b0000000000000100
S2 5.90
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=1
Input:
S15-S0 = 0x0008 = 0b0000000000001000
S3 6.70
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=1 m7_40=0 m7_95=0 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=1
Input:
S15-S0 = 0x0010 = 0b0000000000010000
S4 7.40
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
Input:
S15-S0 = 0x0020 = 0b0000000000100000
S5 7.95
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
Input:
S15-S0 = 0x0040 = 0b0000000001000000
S6 10.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=1 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=0
Input:
S15-S0 = 0x0080 = 0b0000000010000000
S7 12.2
Output:
cfg.smod=0 spare=0 icmi=1 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=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
m4_75=0 m5_15=0 m5_90=0 m6_70=1 m7_40=1 m7_95=0 m10_2=1 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=0
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 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
m4_75=0 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
Result invalid!
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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 m5_15=0 m5_90=0 m6_70=1 m7_40=1 m7_95=1 m10_2=0 m12_2=0
Result invalid!
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 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=1
m4_75=0 m5_15=0 m5_90=0 m6_70=0 m7_40=0 m7_95=0 m10_2=0 m12_2=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_15=0 m5_90=1 m6_70=0 m7_40=1 m7_95=0 m10_2=0 m12_2=1
Result invalid!
cfg.smod=0 spare=0 icmi=0 nscb=0 ver=1
m4_75=1 m5_15=0 m5_90=1 m6_70=0 m7_40=0 m7_95=1 m10_2=0 m12_2=1
test_cell_id_matching