Change in osmo-pcu[master]: Get rid of class GprsCodingScheme

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

pespin gerrit-no-reply at lists.osmocom.org
Mon May 18 12:24:32 UTC 2020


pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcu/+/18351 )


Change subject: Get rid of class GprsCodingScheme
......................................................................

Get rid of class GprsCodingScheme

We have same kind of object splitted into two layers, in coding_scheme
and gprs_coding_scheme. Let's merge them together and get rid of the
class, which is not really useful because it's only a set of functions
operating on one enum value.

This change also fixes gcc 10.1.0 error about memseting a complex type
in rlc.h init().

Change-Id: Ie9ce2144ba9e8dbba9704d4e0000a2929e3e41df
---
M src/Makefile.am
M src/bts.h
M src/coding_scheme.c
M src/coding_scheme.h
M src/decoding.cpp
M src/decoding.h
M src/encoding.cpp
M src/encoding.h
M src/gprs_bssgp_pcu.cpp
D src/gprs_coding_scheme.cpp
D src/gprs_coding_scheme.h
M src/gprs_ms.cpp
M src/gprs_ms.h
M src/pcu_main.cpp
M src/pcu_vty_functions.cpp
M src/pdch.cpp
M src/pdch.h
M src/rlc.cpp
M src/rlc.h
M src/tbf.cpp
M src/tbf.h
M src/tbf_dl.cpp
M src/tbf_dl.h
M src/tbf_ul.cpp
M tests/edge/EdgeTest.cpp
M tests/tbf/TbfTest.cpp
26 files changed, 530 insertions(+), 669 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/51/18351/1

diff --git a/src/Makefile.am b/src/Makefile.am
index 54c6f1b..ece372d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,7 +68,6 @@
 	osmobts_sock.cpp \
 	gprs_codel.c \
 	coding_scheme.c \
-	gprs_coding_scheme.cpp \
 	egprs_rlc_compression.cpp \
 	gprs_rlcmac_sched.cpp
 
@@ -104,7 +103,6 @@
 	pcu_utils.h \
 	cxx_linuxlist.h \
 	gprs_codel.h \
-	gprs_coding_scheme.h \
 	coding_scheme.h \
 	egprs_rlc_compression.h \
 	wireshark_compat.h
diff --git a/src/bts.h b/src/bts.h
index 15dd482..9986bdc 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -37,7 +37,7 @@
 #include "sba.h"
 #include "tbf.h"
 #include "gprs_ms_storage.h"
-#include "gprs_coding_scheme.h"
+#include "coding_scheme.h"
 #include <cxx_linuxlist.h>
 #endif
 
diff --git a/src/coding_scheme.c b/src/coding_scheme.c
index eaa4953..9848432 100644
--- a/src/coding_scheme.c
+++ b/src/coding_scheme.c
@@ -42,6 +42,56 @@
 	{ 0, NULL }
 };
 
+enum Family {
+	FAMILY_INVALID,
+	FAMILY_A,
+	FAMILY_B,
+	FAMILY_C,
+};
+
+static struct {
+	struct {
+		uint8_t bytes;
+		uint8_t ext_bits;
+		uint8_t data_header_bits;
+	} uplink, downlink;
+	uint8_t data_bytes;
+	uint8_t optional_padding_bits;
+	enum HeaderType data_hdr;
+	enum Family family;
+} mcs_info[NUM_SCHEMES] = {
+	{{0, 0},   {0, 0},    0,  0,
+		HEADER_INVALID, FAMILY_INVALID},
+	{{23, 0},  {23, 0},  20,  0,
+		HEADER_GPRS_DATA, FAMILY_INVALID},
+	{{33, 7},  {33, 7},  30,  0,
+		HEADER_GPRS_DATA, FAMILY_INVALID},
+	{{39, 3},  {39, 3},  36,  0,
+		HEADER_GPRS_DATA, FAMILY_INVALID},
+	{{53, 7},  {53, 7},  50,  0,
+		HEADER_GPRS_DATA, FAMILY_INVALID},
+
+	{{26, 1},  {26, 1},  22,  0,
+		HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
+	{{32, 1},  {32, 1},  28,  0,
+		HEADER_EGPRS_DATA_TYPE_3, FAMILY_B},
+	{{41, 1},  {41, 1},  37, 48,
+		HEADER_EGPRS_DATA_TYPE_3, FAMILY_A},
+	{{48, 1},  {48, 1},  44,  0,
+		HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
+
+	{{60, 7},  {59, 6},  56,  0,
+		HEADER_EGPRS_DATA_TYPE_2, FAMILY_B},
+	{{78, 7},  {77, 6},  74, 48,
+		HEADER_EGPRS_DATA_TYPE_2, FAMILY_A},
+	{{118, 2}, {117, 4}, 56,  0,
+		HEADER_EGPRS_DATA_TYPE_1, FAMILY_B},
+	{{142, 2}, {141, 4}, 68,  0,
+		HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
+	{{154, 2}, {153, 4}, 74,  0,
+		HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
+};
+
 const char *mcs_name(enum CodingScheme val) {
 	return get_value_string(mcs_names, val);
 }
@@ -77,6 +127,194 @@
 	return 0;
 }
 
+enum CodingScheme mcs_get_by_size_ul(unsigned size)
+{
+	switch (size) {
+		case 23: return CS1;
+		case 27: return MCS1;
+		case 33: return MCS2;
+		case 34: return CS2;
+		case 40: return CS3;
+		case 42: return MCS3;
+		case 49: return MCS4;
+		case 54: return CS4;
+		case 61: return MCS5;
+		case 79: return MCS6;
+		case 119: return MCS7;
+		case 143: return MCS8;
+		case 155: return MCS9;
+		default: return UNKNOWN;
+	}
+}
+
+enum CodingScheme mcs_get_gprs_by_num(unsigned num)
+{
+	if (num < 1 || num > 4)
+		return UNKNOWN;
+	return CS1 + (num - 1);
+}
+
+enum CodingScheme mcs_get_egprs_by_num(unsigned num)
+{
+	if (num < 1 || num > 9)
+		return UNKNOWN;
+	return MCS1 + (num - 1);
+}
+
+bool mcs_is_valid(enum CodingScheme cs)
+{
+	return UNKNOWN <= cs && cs <= MCS9;
+}
+
+bool mcs_is_compat_kind(enum CodingScheme cs, enum mcs_kind mode)
+{
+	switch (mode) {
+	case GPRS: return mcs_is_gprs(cs);
+	case EGPRS_GMSK: return mcs_is_edge_gmsk(cs);
+	case EGPRS: return mcs_is_edge(cs);
+	}
+
+	return false;
+}
+
+bool mcs_is_compat(enum CodingScheme cs, enum CodingScheme o)
+{
+	return (mcs_is_gprs(cs) && mcs_is_gprs(o)) || (mcs_is_edge(cs) && mcs_is_edge(o));
+}
+
+uint8_t mcs_size_ul(enum CodingScheme cs)
+{
+	return mcs_info[cs].uplink.bytes + (mcs_spare_bits_ul(cs) ? 1 : 0);
+}
+
+uint8_t mcs_size_dl(enum CodingScheme cs)
+{
+	return mcs_info[cs].downlink.bytes + (mcs_spare_bits_dl(cs) ? 1 : 0);
+}
+
+uint8_t mcs_used_size_ul(enum CodingScheme cs)
+{
+	if (mcs_info[cs].data_hdr == HEADER_GPRS_DATA)
+		return mcs_info[cs].uplink.bytes;
+	else
+		return mcs_size_ul(cs);
+}
+
+uint8_t mcs_used_size_dl(enum CodingScheme cs)
+{
+	if (mcs_info[cs].data_hdr == HEADER_GPRS_DATA)
+		return mcs_info[cs].downlink.bytes;
+	else
+		return mcs_size_dl(cs);
+}
+
+uint8_t mcs_max_bytes_ul(enum CodingScheme cs)
+{
+	return mcs_info[cs].uplink.bytes;
+}
+
+uint8_t mcs_max_bytes_dl(enum CodingScheme cs)
+{
+	return mcs_info[cs].downlink.bytes;
+}
+
+uint8_t mcs_spare_bits_ul(enum CodingScheme cs)
+{
+	return mcs_info[cs].uplink.ext_bits;
+}
+
+uint8_t mcs_spare_bits_dl(enum CodingScheme cs)
+{
+return mcs_info[cs].downlink.ext_bits;
+}
+
+uint8_t mcs_max_data_block_bytes(enum CodingScheme cs)
+{
+	return mcs_info[cs].data_bytes;
+}
+
+uint8_t mcs_opt_padding_bits(enum CodingScheme cs)
+{
+	return mcs_info[cs].optional_padding_bits;
+}
+
+void mcs_inc_kind(enum CodingScheme *cs, enum mcs_kind mode)
+{
+	if (!mcs_is_compat_kind(*cs, mode))
+		/* This should not happen. TODO: Use assert? */
+		return;
+
+	enum CodingScheme new_cs = *cs + 1;
+	if (!mcs_is_compat_kind(new_cs, mode))
+		/* Clipping, do not change the value */
+		return;
+
+	*cs = new_cs;
+}
+
+void mcs_dec_kind(enum CodingScheme *cs, enum mcs_kind mode)
+{
+	if (!mcs_is_compat_kind(*cs, mode))
+		/* This should not happen. TODO: Use assert? */
+		return;
+
+	enum CodingScheme new_cs = *cs - 1;
+	if (!mcs_is_compat_kind(new_cs, mode))
+		/* Clipping, do not change the value */
+		return;
+
+	*cs = new_cs;
+}
+
+void mcs_inc(enum CodingScheme *cs)
+{
+	if (mcs_is_gprs(*cs) && *cs == CS4)
+		return;
+
+	if (mcs_is_edge(*cs) && *cs == MCS9)
+		return;
+
+	if (!mcs_is_valid(*cs))
+		return;
+
+	*cs = *cs + 1;
+}
+
+void mcs_dec(enum CodingScheme *cs)
+{
+	if (mcs_is_gprs(*cs) && *cs == CS1)
+		return;
+
+	if (mcs_is_edge(*cs) && *cs == MCS1)
+		return;
+
+	if (!mcs_is_valid(*cs))
+		return;
+
+	*cs = *cs - 1;
+}
+
+bool mcs_is_family_compat(enum CodingScheme cs, enum CodingScheme o)
+{
+	if (cs == o)
+		return true;
+
+	if (mcs_info[cs].family == FAMILY_INVALID)
+		return false;
+
+	return mcs_info[cs].family == mcs_info[o].family;
+}
+
+void mcs_dec_to_single_block(enum CodingScheme *cs, bool *needStuffing)
+{
+	switch (*cs) {
+	case MCS7: *needStuffing = false; *cs = MCS5; break;
+	case MCS8: *needStuffing =  true; *cs = MCS6; break;
+	case MCS9: *needStuffing = false; *cs = MCS6; break;
+	default:   *needStuffing = false; break;
+	}
+}
+
 static struct {
 	struct {
 		uint8_t data_header_bits;
@@ -93,6 +331,11 @@
 	{ { 3 * 8 + 7 }, { 3 * 8 + 7 }, 2, 1, "EGPRS_DATA_TYPE3" },
 };
 
+enum HeaderType mcs_header_type(enum CodingScheme mcs)
+{
+	return mcs_info[mcs].data_hdr;
+}
+
 uint8_t num_data_blocks(enum HeaderType ht)
 {
 	OSMO_ASSERT(ht < NUM_HEADER_TYPES);
diff --git a/src/coding_scheme.h b/src/coding_scheme.h
index 24db86d..8800f0c 100644
--- a/src/coding_scheme.h
+++ b/src/coding_scheme.h
@@ -21,6 +21,8 @@
 
 #include <osmocom/core/utils.h>
 
+#include <stdbool.h>
+
 enum CodingScheme {
 	UNKNOWN,
 	/* GPRS Coding Schemes: */
@@ -30,6 +32,15 @@
 	NUM_SCHEMES
 };
 
+enum mcs_kind {
+	GPRS,
+	EGPRS_GMSK,
+	EGPRS,
+};
+
+#define EGPRS_ARQ1            0x0
+#define EGPRS_ARQ2            0x1
+
 extern const struct value_string mcs_names[];
 const char *mcs_name(enum CodingScheme val);
 enum CodingScheme get_retx_mcs(enum CodingScheme initial_mcs, enum CodingScheme commanded_mcs, bool resegment_bit);
@@ -40,6 +51,32 @@
 
 uint8_t mcs_chan_code(enum CodingScheme cs);
 
+enum CodingScheme mcs_get_by_size_ul(unsigned size);
+enum CodingScheme mcs_get_gprs_by_num(unsigned num);
+enum CodingScheme mcs_get_egprs_by_num(unsigned num);
+bool mcs_is_valid(enum CodingScheme cs);
+bool mcs_is_compat(enum CodingScheme cs, enum CodingScheme o);
+bool mcs_is_compat_kind(enum CodingScheme cs, enum mcs_kind mode);
+
+uint8_t mcs_size_ul(enum CodingScheme cs);
+uint8_t mcs_size_dl(enum CodingScheme cs);
+uint8_t mcs_used_size_ul(enum CodingScheme cs);
+uint8_t mcs_used_size_dl(enum CodingScheme cs);
+uint8_t mcs_max_bytes_ul(enum CodingScheme cs);
+uint8_t mcs_max_bytes_dl(enum CodingScheme cs);
+uint8_t mcs_spare_bits_ul(enum CodingScheme cs);
+uint8_t mcs_spare_bits_dl(enum CodingScheme cs);
+uint8_t mcs_max_data_block_bytes(enum CodingScheme cs);
+uint8_t mcs_opt_padding_bits(enum CodingScheme cs);
+
+void mcs_inc_kind(enum CodingScheme *cs, enum mcs_kind mode);
+void mcs_dec_kind(enum CodingScheme *cs, enum mcs_kind mode);
+void mcs_inc(enum CodingScheme *cs);
+void mcs_dec(enum CodingScheme *cs);
+
+bool mcs_is_family_compat(enum CodingScheme cs, enum CodingScheme o);
+void mcs_dec_to_single_block(enum CodingScheme *cs, bool *needStuffing);
+
 enum HeaderType {
 	HEADER_INVALID,
 	HEADER_GPRS_CONTROL,
@@ -50,17 +87,11 @@
 	NUM_HEADER_TYPES
 };
 
-enum HeaderType headerTypeData(enum CodingScheme mcs);
+enum HeaderType mcs_header_type(enum CodingScheme mcs);
 
 uint8_t num_data_blocks(enum HeaderType ht);
 uint8_t num_data_header_bits_UL(enum HeaderType ht);
 uint8_t num_data_header_bits_DL(enum HeaderType ht);
 uint8_t num_data_block_header_bits(enum HeaderType ht);
 
-enum mcs_kind {
-	GPRS,
-	EGPRS_GMSK,
-	EGPRS,
-};
-
 const char *mode_name(enum mcs_kind val);
diff --git a/src/decoding.cpp b/src/decoding.cpp
index 99a17dc..7b9ae06 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -189,7 +189,7 @@
 }
 
 int Decoding::rlc_data_from_ul_data(
-	const struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
+	const struct gprs_rlc_data_block_info *rdbi, CodingScheme cs,
 	const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
 	uint32_t *tlli)
 {
@@ -351,10 +351,10 @@
 }
 
 int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
-	const uint8_t *data, GprsCodingScheme cs)
+	const uint8_t *data, CodingScheme cs)
 {
 	unsigned int cur_bit = 0;
-	switch(cs.headerTypeData()) {
+	switch(mcs_header_type(cs)) {
 	case HEADER_GPRS_DATA :
 		cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
 		break;
@@ -380,7 +380,7 @@
 int Decoding::rlc_parse_ul_data_header_egprs_type_3(
 	struct gprs_rlc_data_info *rlc,
 	const uint8_t *data,
-	const GprsCodingScheme &cs)
+	const CodingScheme &cs)
 {
 	int punct, punct2, with_padding, cps;
 	unsigned int e_ti_header, offs, cur_bit = 0;
@@ -414,7 +414,7 @@
 	rlc->block_info[0].ti  = !!(e_ti_header & 0x02);
 	cur_bit += 2;
 	/* skip data area */
-	cur_bit += cs.maxDataBlockBytes() * 8;
+	cur_bit += mcs_max_data_block_bytes(cs) * 8;
 
 	return cur_bit;
 }
@@ -422,7 +422,7 @@
 int Decoding::rlc_parse_ul_data_header_egprs_type_2(
 	struct gprs_rlc_data_info *rlc,
 	const uint8_t *data,
-	const GprsCodingScheme &cs)
+	const CodingScheme &cs)
 {
 	const struct gprs_rlc_ul_header_egprs_2 *egprs2;
 	unsigned int e_ti_header, offs, cur_bit = 0;
@@ -458,14 +458,14 @@
 	cur_bit += 2;
 
 	/* skip data area */
-	cur_bit += cs.maxDataBlockBytes() * 8;
+	cur_bit += mcs_max_data_block_bytes(cs) * 8;
 
 	return cur_bit;
 }
 
 int Decoding::rlc_parse_ul_data_header_egprs_type_1(
 	struct gprs_rlc_data_info *rlc,
-	const uint8_t *data, const GprsCodingScheme &cs)
+	const uint8_t *data, const CodingScheme &cs)
 {
 	struct gprs_rlc_ul_header_egprs_1 *egprs1;
 	unsigned int e_ti_header, cur_bit = 0, offs;
@@ -517,13 +517,13 @@
 	rlc->block_info[1].ti  = !!(e_ti_header & 0x02);
 	cur_bit += 2;
 	/* skip data area */
-	cur_bit += cs.maxDataBlockBytes() * 8;
+	cur_bit += mcs_max_data_block_bytes(cs) * 8;
 
 	return cur_bit;
 }
 
 int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
-	const uint8_t *data, const GprsCodingScheme &cs)
+	const uint8_t *data, const CodingScheme &cs)
 {
 	const struct rlc_ul_header *gprs;
 	unsigned int cur_bit = 0;
@@ -547,7 +547,7 @@
 	rlc->block_info[0].spb = 0;
 	cur_bit += rlc->data_offs_bits[0];
 	/* skip data area */
-	cur_bit += cs.maxDataBlockBytes() * 8;
+	cur_bit += mcs_max_data_block_bytes(cs) * 8;
 
 	return cur_bit;
 }
diff --git a/src/decoding.h b/src/decoding.h
index cadb80c..695c4b4 100644
--- a/src/decoding.h
+++ b/src/decoding.h
@@ -40,7 +40,7 @@
 
 	static int rlc_data_from_ul_data(
 		const struct gprs_rlc_data_block_info *rdbi,
-		GprsCodingScheme cs, const uint8_t *data, RlcData *chunks,
+		CodingScheme cs, const uint8_t *data, RlcData *chunks,
 		unsigned int chunks_size, uint32_t *tlli);
 	static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
 	static uint8_t get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
@@ -50,21 +50,21 @@
 	static int rlc_parse_ul_data_header_egprs_type_3(
 		struct gprs_rlc_data_info *rlc,
 		const uint8_t *data,
-		const GprsCodingScheme &cs);
+		const CodingScheme &cs);
 	static int rlc_parse_ul_data_header_egprs_type_2(
 		struct gprs_rlc_data_info *rlc,
 		const uint8_t *data,
-		const GprsCodingScheme &cs);
+		const CodingScheme &cs);
 	static int rlc_parse_ul_data_header_egprs_type_1(
 		struct gprs_rlc_data_info *rlc,
 		const uint8_t *data,
-		const GprsCodingScheme &cs);
+		const CodingScheme &cs);
 	static int rlc_parse_ul_data_header_gprs(
 		struct gprs_rlc_data_info *rlc,
 		const uint8_t *data,
-		const GprsCodingScheme &cs);
+		const CodingScheme &cs);
 	static int rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
-		const uint8_t *data, GprsCodingScheme cs);
+		const uint8_t *data, CodingScheme cs);
 	static unsigned int rlc_copy_to_aligned_buffer(
 		const struct gprs_rlc_data_info *rlc,
 		unsigned int data_block_idx,
diff --git a/src/encoding.cpp b/src/encoding.cpp
index a4a14dd..619f2ec 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -1107,11 +1107,11 @@
 	struct gprs_rlc_dl_header_egprs_3 *egprs3;
 	struct rlc_dl_header *gprs;
 	unsigned int e_fbi_header;
-	GprsCodingScheme cs = rlc->cs;
+	CodingScheme cs = rlc->cs;
 	unsigned int offs;
 	unsigned int bsn_delta;
 
-	switch(cs.headerTypeData()) {
+	switch(mcs_header_type(cs)) {
 	case HEADER_GPRS_DATA:
 		gprs = static_cast<struct rlc_dl_header *>
 			((void *)data);
@@ -1595,7 +1595,7 @@
  * \return the state of the rlc/mac like if there is more space for another chunk
  */
 Encoding::AppendResult Encoding::rlc_data_to_dl_append(
-	struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
+	struct gprs_rlc_data_block_info *rdbi, CodingScheme cs,
 	gprs_llc *llc, int *offset, int *num_chunks,
 	uint8_t *data_block, bool is_final, int *count_payload)
 {
diff --git a/src/encoding.h b/src/encoding.h
index 2365f07..33290c1 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -21,9 +21,10 @@
 #pragma once
 
 #include <stdint.h>
-#include <gprs_coding_scheme.h>
+
 extern "C" {
 #include <osmocom/gsm/l1sap.h>
+#include "coding_scheme.h"
 #include "gsm_rlcmac.h"
 }
 
@@ -99,7 +100,7 @@
 	};
 
 	static AppendResult rlc_data_to_dl_append(
-		struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
+		struct gprs_rlc_data_block_info *rdbi, CodingScheme cs,
 		gprs_llc *llc, int *offset, int *num_chunks,
 		uint8_t *data, bool is_final, int *count_payload);
 };
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index b8e746a..9e293a8 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -24,7 +24,7 @@
 #include <gprs_debug.h>
 #include <bts.h>
 #include <tbf.h>
-#include <gprs_coding_scheme.h>
+#include <coding_scheme.h>
 #include <pdch.h>
 #include <decoding.h>
 
@@ -639,9 +639,9 @@
 	return num_pdch;
 }
 
-static uint32_t gprs_bssgp_max_leak_rate(GprsCodingScheme cs, int num_pdch)
+static uint32_t gprs_bssgp_max_leak_rate(CodingScheme cs, int num_pdch)
 {
-	int bytes_per_rlc_block = cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData());
+	int bytes_per_rlc_block = mcs_max_data_block_bytes(cs) * num_data_blocks(mcs_header_type(cs));
 
 	/* n byte payload per 20ms */
 	return bytes_per_rlc_block * (1000 / 20) * num_pdch;
@@ -717,7 +717,7 @@
 	return rate;
 }
 
-static GprsCodingScheme max_coding_scheme_dl(struct gprs_rlcmac_bts *bts)
+static CodingScheme max_coding_scheme_dl(struct gprs_rlcmac_bts *bts)
 {
 	int num;
 
@@ -733,7 +733,7 @@
 			num = 9;
 		}
 
-		return GprsCodingScheme::getEgprsByNum(num);
+		return mcs_get_egprs_by_num(num);
 	}
 
 	if (!bts->cs_adj_enabled) {
@@ -753,7 +753,7 @@
 		num = 4;
 	}
 
-	return GprsCodingScheme::getGprsByNum(num);
+	return mcs_get_gprs_by_num(num);
 }
 
 static int gprs_bssgp_tx_fc_bvc(void)
@@ -765,7 +765,7 @@
 	uint32_t ms_leak_rate; /* oct/s */
 	uint32_t avg_delay_ms;
 	int num_pdch = -1;
-	GprsCodingScheme max_cs_dl;
+	CodingScheme max_cs_dl;
 
 	if (!the_pcu.bctx) {
 		LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
diff --git a/src/gprs_coding_scheme.cpp b/src/gprs_coding_scheme.cpp
deleted file mode 100644
index 0c22670..0000000
--- a/src/gprs_coding_scheme.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-/* gprs_coding_scheme.cpp
- *
- * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
- * Author: Jacob Erlbeck <jerlbeck at sysmocom.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-
-#include "gprs_coding_scheme.h"
-
-enum Family {
-	FAMILY_INVALID,
-	FAMILY_A,
-	FAMILY_B,
-	FAMILY_C,
-};
-
-static struct {
-	struct {
-		uint8_t bytes;
-		uint8_t ext_bits;
-		uint8_t data_header_bits;
-	} uplink, downlink;
-	uint8_t data_bytes;
-	uint8_t optional_padding_bits;
-	enum HeaderType data_hdr;
-	enum Family family;
-} mcs_info[NUM_SCHEMES] = {
-	{{0, 0},   {0, 0},    0,  0,
-		HEADER_INVALID, FAMILY_INVALID},
-	{{23, 0},  {23, 0},  20,  0,
-		HEADER_GPRS_DATA, FAMILY_INVALID},
-	{{33, 7},  {33, 7},  30,  0,
-		HEADER_GPRS_DATA, FAMILY_INVALID},
-	{{39, 3},  {39, 3},  36,  0,
-		HEADER_GPRS_DATA, FAMILY_INVALID},
-	{{53, 7},  {53, 7},  50,  0,
-		HEADER_GPRS_DATA, FAMILY_INVALID},
-
-	{{26, 1},  {26, 1},  22,  0,
-		HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
-	{{32, 1},  {32, 1},  28,  0,
-		HEADER_EGPRS_DATA_TYPE_3, FAMILY_B},
-	{{41, 1},  {41, 1},  37, 48,
-		HEADER_EGPRS_DATA_TYPE_3, FAMILY_A},
-	{{48, 1},  {48, 1},  44,  0,
-		HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
-
-	{{60, 7},  {59, 6},  56,  0,
-		HEADER_EGPRS_DATA_TYPE_2, FAMILY_B},
-	{{78, 7},  {77, 6},  74, 48,
-		HEADER_EGPRS_DATA_TYPE_2, FAMILY_A},
-	{{118, 2}, {117, 4}, 56,  0,
-		HEADER_EGPRS_DATA_TYPE_1, FAMILY_B},
-	{{142, 2}, {141, 4}, 68,  0,
-		HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
-	{{154, 2}, {153, 4}, 74,  0,
-		HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
-};
-
-GprsCodingScheme GprsCodingScheme::getBySizeUL(unsigned size)
-{
-	switch (size) {
-		case 23: return GprsCodingScheme(CS1);
-		case 27: return GprsCodingScheme(MCS1);
-		case 33: return GprsCodingScheme(MCS2);
-		case 34: return GprsCodingScheme(CS2);
-		case 40: return GprsCodingScheme(CS3);
-		case 42: return GprsCodingScheme(MCS3);
-		case 49: return GprsCodingScheme(MCS4);
-		case 54: return GprsCodingScheme(CS4);
-		case 61: return GprsCodingScheme(MCS5);
-		case 79: return GprsCodingScheme(MCS6);
-		case 119: return GprsCodingScheme(MCS7);
-		case 143: return GprsCodingScheme(MCS8);
-		case 155: return GprsCodingScheme(MCS9);
-	}
-
-	return GprsCodingScheme(UNKNOWN);
-}
-
-uint8_t GprsCodingScheme::sizeUL() const
-{
-	return mcs_info[m_scheme].uplink.bytes + (spareBitsUL() ? 1 : 0);
-}
-
-uint8_t GprsCodingScheme::usedSizeUL() const
-{
-	if (mcs_info[m_scheme].data_hdr == HEADER_GPRS_DATA)
-		return mcs_info[m_scheme].uplink.bytes;
-	else
-		return sizeUL();
-}
-
-uint8_t GprsCodingScheme::maxBytesUL() const
-{
-	return mcs_info[m_scheme].uplink.bytes;
-}
-
-uint8_t GprsCodingScheme::spareBitsUL() const
-{
-	return mcs_info[m_scheme].uplink.ext_bits;
-}
-
-uint8_t GprsCodingScheme::sizeDL() const
-{
-	return mcs_info[m_scheme].downlink.bytes + (spareBitsDL() ? 1 : 0);
-}
-
-uint8_t GprsCodingScheme::usedSizeDL() const
-{
-	if (mcs_info[m_scheme].data_hdr == HEADER_GPRS_DATA)
-		return mcs_info[m_scheme].downlink.bytes;
-	else
-		return sizeDL();
-}
-
-uint8_t GprsCodingScheme::maxBytesDL() const
-{
-	return mcs_info[m_scheme].downlink.bytes;
-}
-
-uint8_t GprsCodingScheme::spareBitsDL() const
-{
-	return mcs_info[m_scheme].downlink.ext_bits;
-}
-
-uint8_t GprsCodingScheme::maxDataBlockBytes() const
-{
-	return mcs_info[m_scheme].data_bytes;
-}
-
-uint8_t GprsCodingScheme::optionalPaddingBits() const
-{
-	return mcs_info[m_scheme].optional_padding_bits;
-}
-
-enum HeaderType GprsCodingScheme::headerTypeData() const
-{
-	return mcs_info[m_scheme].data_hdr;
-}
-
-void GprsCodingScheme::inc(enum mcs_kind mode)
-{
-	if (!isCompatible(mode))
-		/* This should not happen. TODO: Use assert? */
-		return;
-
-	CodingScheme new_cs(CodingScheme(m_scheme + 1));
-	if (!GprsCodingScheme(new_cs).isCompatible(mode))
-		/* Clipping, do not change the value */
-		return;
-
-	m_scheme = new_cs;
-}
-
-void GprsCodingScheme::dec(enum mcs_kind mode)
-{
-	if (!isCompatible(mode))
-		/* This should not happen. TODO: Use assert? */
-		return;
-
-	CodingScheme new_cs(CodingScheme(m_scheme - 1));
-	if (!GprsCodingScheme(new_cs).isCompatible(mode))
-		/* Clipping, do not change the value */
-		return;
-
-	m_scheme = new_cs;
-}
-
-void GprsCodingScheme::inc()
-{
-	if (mcs_is_gprs(m_scheme) && m_scheme == CS4)
-		return;
-
-	if (mcs_is_edge(m_scheme) && m_scheme == MCS9)
-		return;
-
-	if (!isValid())
-		return;
-
-	m_scheme = CodingScheme(m_scheme + 1);
-}
-
-void GprsCodingScheme::dec()
-{
-	if (mcs_is_gprs(m_scheme) && m_scheme == CS1)
-		return;
-
-	if (mcs_is_edge(m_scheme) && m_scheme == MCS1)
-		return;
-
-	if (!isValid())
-		return;
-
-	m_scheme = CodingScheme(m_scheme - 1);
-}
-
-bool GprsCodingScheme::isFamilyCompatible(GprsCodingScheme o) const
-{
-	if (*this == o)
-		return true;
-
-	if (mcs_info[m_scheme].family == FAMILY_INVALID)
-		return false;
-
-	return mcs_info[m_scheme].family == mcs_info[o.m_scheme].family;
-}
-
-void GprsCodingScheme::decToSingleBlock(bool *needStuffing)
-{
-	switch (m_scheme) {
-	case MCS7: *needStuffing = false; m_scheme = MCS5; break;
-	case MCS8: *needStuffing =  true; m_scheme = MCS6; break;
-	case MCS9: *needStuffing = false; m_scheme = MCS6; break;
-	default:   *needStuffing = false; break;
-	}
-}
diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h
deleted file mode 100644
index c31f58f..0000000
--- a/src/gprs_coding_scheme.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* gprs_coding_scheme.h
- *
- * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
- * Author: Jacob Erlbeck <jerlbeck at sysmocom.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <stddef.h>
-
-extern "C" {
-	#include <osmocom/core/utils.h>
-	#include "coding_scheme.h"
-}
-
-class GprsCodingScheme {
-public:
-
-#define EGPRS_ARQ1            0x0
-#define EGPRS_ARQ2            0x1
-
-	GprsCodingScheme(CodingScheme s = UNKNOWN);
-
-	operator bool() const {return m_scheme != UNKNOWN;}
-	operator CodingScheme() const {return m_scheme;}
-	uint8_t to_num() const;
-
-	GprsCodingScheme& operator =(CodingScheme s);
-	bool operator == (CodingScheme s) const;
-	GprsCodingScheme& operator =(GprsCodingScheme o);
-
-	bool isValid()   const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
-
-	bool isCompatible(enum mcs_kind mode) const;
-	bool isCompatible(GprsCodingScheme o) const;
-	bool isFamilyCompatible(GprsCodingScheme o) const;
-
-	void inc(enum mcs_kind mode);
-	void dec(enum mcs_kind mode);
-	void inc();
-	void dec();
-	void decToSingleBlock(bool *needStuffing);
-
-	uint8_t sizeUL() const;
-	uint8_t sizeDL() const;
-	uint8_t usedSizeUL() const;
-	uint8_t usedSizeDL() const;
-	uint8_t maxBytesUL() const;
-	uint8_t maxBytesDL() const;
-	uint8_t spareBitsUL() const;
-	uint8_t spareBitsDL() const;
-	uint8_t maxDataBlockBytes() const;
-	uint8_t optionalPaddingBits() const;
-
-	enum HeaderType headerTypeData() const;
-
-	static GprsCodingScheme getBySizeUL(unsigned size);
-	static GprsCodingScheme getGprsByNum(unsigned num);
-	static GprsCodingScheme getEgprsByNum(unsigned num);
-
-private:
-	GprsCodingScheme(int s); /* fail on use */
-	GprsCodingScheme& operator =(int s); /* fail on use */
-	enum CodingScheme m_scheme;
-};
-
-// FIXME: remove once < comparison operator below is no longer necessary
-inline uint8_t GprsCodingScheme::to_num() const
-{
-	if (mcs_is_gprs(m_scheme))
-		return (m_scheme - CS1) + 1;
-
-	if (mcs_is_edge(m_scheme))
-		return (m_scheme - MCS1) + 1;
-
-	return 0;
-}
-
-inline bool GprsCodingScheme::isCompatible(enum mcs_kind mode) const
-{
-	switch (mode) {
-	case GPRS: return mcs_is_gprs(m_scheme);
-	case EGPRS_GMSK: return mcs_is_edge_gmsk(m_scheme);
-	case EGPRS: return mcs_is_edge(m_scheme);
-	}
-
-	return false;
-}
-
-inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
-{
-	return (mcs_is_gprs(m_scheme) && mcs_is_gprs(o)) || (mcs_is_edge(m_scheme) && mcs_is_edge(o));
-}
-
-inline GprsCodingScheme::GprsCodingScheme(CodingScheme s)
-	: m_scheme(s)
-{
-	if (!isValid())
-		m_scheme = UNKNOWN;
-}
-
-inline GprsCodingScheme& GprsCodingScheme::operator =(CodingScheme s)
-{
-	m_scheme = s;
-
-	if (!isValid())
-		m_scheme = UNKNOWN;
-
-	return *this;
-}
-
-inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
-{
-	m_scheme = o.m_scheme;
-	return *this;
-}
-
-inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
-{
-	if (num < 1 || num > 4)
-		return GprsCodingScheme();
-
-	return GprsCodingScheme(CodingScheme(CS1 + (num - 1)));
-}
-
-inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
-{
-	if (num < 1 || num > 9)
-		return GprsCodingScheme();
-
-	return GprsCodingScheme(CodingScheme(MCS1 + (num - 1)));
-}
-
-/* The coding schemes form a partial ordering */
-inline bool GprsCodingScheme::operator == (CodingScheme scheme) const
-{
-	return this->m_scheme == scheme;
-}
-
-inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
-{
-	return !(a == b);
-}
-
-inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
-{
-	return a.isCompatible(b) && a.to_num() < b.to_num();
-}
diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp
index 102f558..68d7640 100644
--- a/src/gprs_ms.cpp
+++ b/src/gprs_ms.cpp
@@ -20,7 +20,6 @@
 
 
 #include "gprs_ms.h"
-#include <gprs_coding_scheme.h>
 #include "bts.h"
 #include "tbf.h"
 #include "tbf_ul.h"
@@ -103,6 +102,8 @@
 	m_ta(GSM48_TA_INVALID),
 	m_ms_class(0),
 	m_egprs_ms_class(0),
+	m_current_cs_ul(UNKNOWN),
+	m_current_cs_dl(UNKNOWN),
 	m_is_idle(true),
 	m_ref(0),
 	m_list(this),
@@ -226,15 +227,15 @@
 	switch (m_mode) {
 	case GPRS:
 		if (!mcs_is_gprs(m_current_cs_ul)) {
-			m_current_cs_ul = GprsCodingScheme::getGprsByNum(
+			m_current_cs_ul = mcs_get_gprs_by_num(
 				m_bts->bts_data()->initial_cs_ul);
-			if (!m_current_cs_ul.isValid())
+			if (!mcs_is_valid(m_current_cs_ul))
 				m_current_cs_ul = CS1;
 		}
 		if (!mcs_is_gprs(m_current_cs_dl)) {
-			m_current_cs_dl = GprsCodingScheme::getGprsByNum(
+			m_current_cs_dl = mcs_get_gprs_by_num(
 				m_bts->bts_data()->initial_cs_dl);
-			if (!m_current_cs_dl.isValid())
+			if (!mcs_is_valid(m_current_cs_dl))
 				m_current_cs_dl = CS1;
 		}
 		break;
@@ -242,15 +243,15 @@
 	case EGPRS_GMSK:
 	case EGPRS:
 		if (!mcs_is_edge(m_current_cs_ul)) {
-			m_current_cs_ul = GprsCodingScheme::getEgprsByNum(
+			m_current_cs_ul = mcs_get_egprs_by_num(
 				m_bts->bts_data()->initial_mcs_ul);
-			if (!m_current_cs_ul.isValid())
+			if (!mcs_is_valid(m_current_cs_ul))
 				m_current_cs_ul = MCS1;
 		}
 		if (!mcs_is_edge(m_current_cs_dl)) {
-			m_current_cs_dl = GprsCodingScheme::getEgprsByNum(
+			m_current_cs_dl = mcs_get_egprs_by_num(
 				m_bts->bts_data()->initial_mcs_dl);
-			if (!m_current_cs_dl.isValid())
+			if (!mcs_is_valid(m_current_cs_dl))
 				m_current_cs_dl = MCS1;
 		}
 		break;
@@ -510,7 +511,7 @@
 {
 	struct gprs_rlcmac_bts *bts_data;
 	int64_t now;
-	GprsCodingScheme max_cs_dl = this->max_cs_dl();
+	CodingScheme max_cs_dl = this->max_cs_dl();
 
 	OSMO_ASSERT(max_cs_dl);
 	bts_data = m_bts->bts_data();
@@ -527,7 +528,7 @@
 
 	if (error_rate > bts_data->cs_adj_upper_limit) {
 		if (mcs_chan_code(m_current_cs_dl) > 0) {
-			m_current_cs_dl.dec(mode());
+			mcs_dec_kind(&m_current_cs_dl, mode());
 			LOGP(DRLCMACDL, LOGL_INFO,
 				"MS (IMSI %s): High error rate %d%%, "
 				"reducing CS level to %s\n",
@@ -537,7 +538,7 @@
 	} else if (error_rate < bts_data->cs_adj_lower_limit) {
 		if (m_current_cs_dl < max_cs_dl) {
 		       if (now - m_last_cs_not_low > 1000) {
-			       m_current_cs_dl.inc(mode());
+			       mcs_inc_kind(&m_current_cs_dl, mode());
 
 			       LOGP(DRLCMACDL, LOGL_INFO,
 				       "MS (IMSI %s): Low error rate %d%%, "
@@ -560,7 +561,7 @@
 	}
 }
 
-GprsCodingScheme GprsMs::max_cs_ul() const
+CodingScheme GprsMs::max_cs_ul() const
 {
 	struct gprs_rlcmac_bts *bts_data;
 
@@ -568,21 +569,22 @@
 	bts_data = m_bts->bts_data();
 
 	if (mcs_is_gprs(m_current_cs_ul)) {
-		if (!bts_data->max_cs_ul)
-			return GprsCodingScheme(CS4);
+		if (!bts_data->max_cs_ul) {
+			return CS4;
+		}
 
-		return GprsCodingScheme::getGprsByNum(bts_data->max_cs_ul);
+		return mcs_get_gprs_by_num(bts_data->max_cs_ul);
 	}
 
 	if (!mcs_is_edge(m_current_cs_ul))
-		return GprsCodingScheme(); /* UNKNOWN */
+		return UNKNOWN;
 
 	if (bts_data->max_mcs_ul)
-		return GprsCodingScheme::getEgprsByNum(bts_data->max_mcs_ul);
+		return mcs_get_egprs_by_num(bts_data->max_mcs_ul);
 	else if (bts_data->max_cs_ul)
-		return GprsCodingScheme::getEgprsByNum(bts_data->max_cs_ul);
+		return mcs_get_egprs_by_num(bts_data->max_cs_ul);
 
-	return GprsCodingScheme(MCS4);
+	return MCS4;
 }
 
 void GprsMs::set_current_cs_dl(CodingScheme scheme)
@@ -590,7 +592,7 @@
 	m_current_cs_dl = scheme;
 }
 
-GprsCodingScheme GprsMs::max_cs_dl() const
+CodingScheme GprsMs::max_cs_dl() const
 {
 	struct gprs_rlcmac_bts *bts_data;
 
@@ -598,32 +600,33 @@
 	bts_data = m_bts->bts_data();
 
 	if (mcs_is_gprs(m_current_cs_dl)) {
-		if (!bts_data->max_cs_dl)
-			return GprsCodingScheme(CS4);
+		if (!bts_data->max_cs_dl) {
+			return CS4;
+		}
 
-		return GprsCodingScheme::getGprsByNum(bts_data->max_cs_dl);
+		return mcs_get_gprs_by_num(bts_data->max_cs_dl);
 	}
 
 	if (!mcs_is_edge(m_current_cs_dl))
-		return GprsCodingScheme(); /* UNKNOWN */
+		return CodingScheme(); /* UNKNOWN */
 
 	if (bts_data->max_mcs_dl)
-		return GprsCodingScheme::getEgprsByNum(bts_data->max_mcs_dl);
+		return mcs_get_egprs_by_num(bts_data->max_mcs_dl);
 	else if (bts_data->max_cs_dl)
-		return GprsCodingScheme::getEgprsByNum(bts_data->max_cs_dl);
+		return mcs_get_egprs_by_num(bts_data->max_cs_dl);
 
-	return GprsCodingScheme(MCS4);
+	return MCS4;
 }
 
 void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
 {
 	struct gprs_rlcmac_bts *bts_data;
-	GprsCodingScheme max_cs_ul = this->max_cs_ul();
+	CodingScheme max_cs_ul = this->max_cs_ul();
 
 	int old_link_qual;
 	int low;
 	int high;
-	GprsCodingScheme new_cs_ul = m_current_cs_ul;
+	CodingScheme new_cs_ul = m_current_cs_ul;
 	uint8_t current_cs = mcs_chan_code(m_current_cs_ul);
 
 	bts_data = m_bts->bts_data();
@@ -674,10 +677,10 @@
 		old_link_qual = meas->link_qual;
 
 	if (meas->link_qual < low &&  old_link_qual < low)
-		new_cs_ul.dec(mode());
+		mcs_dec_kind(&new_cs_ul, mode());
 	else if (meas->link_qual > high &&  old_link_qual > high &&
 		m_current_cs_ul < max_cs_ul)
-		new_cs_ul.inc(mode());
+		mcs_inc_kind(&new_cs_ul, mode());
 
 	if (m_current_cs_ul != new_cs_ul) {
 		LOGP(DRLCMACMEAS, LOGL_INFO,
@@ -724,9 +727,9 @@
 	}
 }
 
-GprsCodingScheme GprsMs::current_cs_dl() const
+CodingScheme GprsMs::current_cs_dl() const
 {
-	GprsCodingScheme cs = m_current_cs_dl;
+	CodingScheme cs = m_current_cs_dl;
 	size_t unencoded_octets;
 
 	if (!m_bts)
@@ -747,11 +750,11 @@
 		return cs;
 
 	/* The throughput would probably be better if the CS level was reduced */
-	cs.dec(mode());
+	mcs_dec_kind(&cs, mode());
 
 	/* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */
-	if (cs == GprsCodingScheme(CS2))
-		cs.dec(mode());
+	if (cs == CS2)
+		mcs_dec_kind(&cs, mode());
 
 	return cs;
 }
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index 688708e..8836204 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -22,17 +22,17 @@
 
 struct gprs_codel;
 
-#include <gprs_coding_scheme.h>
 #include "cxx_linuxlist.h"
 #include "llc.h"
 #include "tbf.h"
 #include "tbf_dl.h"
 #include "pcu_l1_if.h"
-#include <gprs_coding_scheme.h>
 
 extern "C" {
 	#include <osmocom/core/timer.h>
 	#include <osmocom/core/linuxlist.h>
+
+	#include "coding_scheme.h"
 }
 
 #include <stdint.h>
@@ -89,10 +89,10 @@
 	void set_egprs_ms_class(uint8_t ms_class);
 	void set_current_cs_dl(CodingScheme scheme);
 
-	GprsCodingScheme current_cs_ul() const;
-	GprsCodingScheme current_cs_dl() const;
-	GprsCodingScheme max_cs_ul() const;
-	GprsCodingScheme max_cs_dl() const;
+	CodingScheme current_cs_ul() const;
+	CodingScheme current_cs_dl() const;
+	CodingScheme max_cs_ul() const;
+	CodingScheme max_cs_dl() const;
 
 	int first_common_ts() const;
 	uint8_t dl_slots() const;
@@ -164,8 +164,8 @@
 	uint8_t m_ms_class;
 	uint8_t m_egprs_ms_class;
 	/* current coding scheme */
-	GprsCodingScheme m_current_cs_ul;
-	GprsCodingScheme m_current_cs_dl;
+	CodingScheme m_current_cs_ul;
+	CodingScheme m_current_cs_dl;
 
 	gprs_llc_queue m_llc_queue;
 
@@ -235,7 +235,7 @@
 	return m_egprs_ms_class;
 }
 
-inline GprsCodingScheme GprsMs::current_cs_ul() const
+inline CodingScheme GprsMs::current_cs_ul() const
 {
 	return m_current_cs_ul;
 }
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index a33b655..3912204 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -31,12 +31,12 @@
 #include <signal.h>
 #include <sched.h>
 #include <bts.h>
-#include <gprs_coding_scheme.h>
 #include <osmocom/pcu/pcuif_proto.h>
 #include "gprs_bssgp_pcu.h"
 
 extern "C" {
 #include "pcu_vty.h"
+#include "coding_scheme.h"
 #include <osmocom/gprs/gprs_bssgp.h>
 #include <osmocom/gprs/gprs_ns.h>
 #include <osmocom/vty/telnet_interface.h>
diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp
index 7b6c84f..97241e1 100644
--- a/src/pcu_vty_functions.cpp
+++ b/src/pcu_vty_functions.cpp
@@ -27,7 +27,6 @@
 #include "gprs_ms_storage.h"
 #include "gprs_ms.h"
 #include "cxx_linuxlist.h"
-#include <gprs_coding_scheme.h>
 #include <llc.h>
 #include <pcu_l1_if.h>
 #include <rlc.h>
diff --git a/src/pdch.cpp b/src/pdch.cpp
index fb02d59..953dec4 100644
--- a/src/pdch.cpp
+++ b/src/pdch.cpp
@@ -25,7 +25,7 @@
 #include <encoding.h>
 #include <gprs_rlcmac.h>
 #include <gprs_debug.h>
-#include <gprs_coding_scheme.h>
+#include <coding_scheme.h>
 #include <gprs_ms.h>
 #include <gprs_ms_storage.h>
 #include <pcu_l1_if.h>
@@ -688,11 +688,11 @@
 
 /* Received Uplink RLC control block. */
 int gprs_rlcmac_pdch::rcv_control_block(const uint8_t *data, uint8_t data_len,
-					uint32_t fn, struct pcu_l1_meas *meas, GprsCodingScheme cs)
+					uint32_t fn, struct pcu_l1_meas *meas, CodingScheme cs)
 {
 	bitvec *rlc_block;
 	RlcMacUplink_t *ul_control_block;
-	unsigned len = cs.maxBytesUL();
+	unsigned len = mcs_max_bytes_ul(cs);
 	int rc;
 
 	if (!(rlc_block = bitvec_alloc(len, tall_pcu_ctx)))
@@ -751,7 +751,7 @@
 int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
 	struct pcu_l1_meas *meas)
 {
-	GprsCodingScheme cs = GprsCodingScheme::getBySizeUL(len);
+	CodingScheme cs = mcs_get_by_size_ul(len);
 	if (!cs) {
 		bts()->do_rate_ctr_inc(CTR_DECODE_ERRORS);
 		LOGP(DRLCMACUL, LOGL_ERROR, "Dropping data block with invalid"
@@ -762,7 +762,7 @@
 	bts()->do_rate_ctr_add(CTR_RLC_UL_BYTES, len);
 
 	LOGP(DRLCMACUL, LOGL_DEBUG, "Got RLC block, coding scheme: %s, "
-		"length: %d (%d))\n", mcs_name(cs), len, cs.usedSizeUL());
+		"length: %d (%d))\n", mcs_name(cs), len, mcs_used_size_ul(cs));
 
 	if (mcs_is_gprs(cs))
 		return rcv_block_gprs(data, len, fn, meas, cs);
@@ -778,12 +778,12 @@
 
 /*! \brief process egprs and gprs data blocks */
 int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint8_t data_len, uint32_t fn,
-	struct pcu_l1_meas *meas, GprsCodingScheme cs)
+	struct pcu_l1_meas *meas, CodingScheme cs)
 {
 	int rc;
 	struct gprs_rlc_data_info rlc_dec;
 	struct gprs_rlcmac_ul_tbf *tbf;
-	unsigned len = cs.sizeUL();
+	unsigned len = mcs_size_ul(cs);
 
 	/* These are always data blocks, since EGPRS still uses CS-1 for
 	 * control blocks (see 44.060, section 10.3, 1st par.)
@@ -836,7 +836,7 @@
 }
 
 int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint8_t data_len, uint32_t fn,
-	struct pcu_l1_meas *meas, GprsCodingScheme cs)
+	struct pcu_l1_meas *meas, CodingScheme cs)
 {
 	unsigned payload = data[0] >> 6;
 	int rc = 0;
diff --git a/src/pdch.h b/src/pdch.h
index 97b4b23..1bb028b 100644
--- a/src/pdch.h
+++ b/src/pdch.h
@@ -25,9 +25,9 @@
 extern "C" {
 #include <osmocom/core/linuxlist.h>
 #include "gsm_rlcmac.h"
+#include "coding_scheme.h"
 }
 
-#include <gprs_coding_scheme.h>
 #include <bts.h>
 #endif
 
@@ -61,9 +61,9 @@
 	int rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
 		struct pcu_l1_meas *meas);
 	int rcv_block_gprs(uint8_t *data, uint8_t data_len, uint32_t fn,
-		struct pcu_l1_meas *meas, GprsCodingScheme cs);
+		struct pcu_l1_meas *meas, CodingScheme cs);
 	int rcv_data_block(uint8_t *data, uint8_t data_len, uint32_t fn,
-		struct pcu_l1_meas *meas, GprsCodingScheme cs);
+		struct pcu_l1_meas *meas, CodingScheme cs);
 
 	gprs_rlcmac_bts *bts_data() const;
 	BTS *bts() const;
@@ -113,7 +113,7 @@
 #ifdef __cplusplus
 private:
 	int rcv_control_block(const uint8_t *data, uint8_t data_len, uint32_t fn,
-			      struct pcu_l1_meas *meas, GprsCodingScheme cs);
+			      struct pcu_l1_meas *meas, CodingScheme cs);
 
 	void rcv_control_ack(Packet_Control_Acknowledgement_t *, uint32_t fn);
 	void rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *, uint32_t fn, struct pcu_l1_meas *meas);
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 5316136..bbfb798 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -18,7 +18,6 @@
 
 #include "bts.h"
 #include "gprs_debug.h"
-#include <gprs_coding_scheme.h>
 #include <rlc.h>
 
 #include <stdbool.h>
@@ -29,6 +28,8 @@
 #include <osmocom/core/utils.h>
 #include <osmocom/core/bitvec.h>
 #include <osmocom/core/logging.h>
+
+#include "coding_scheme.h"
 }
 
 
@@ -314,11 +315,11 @@
 }
 
 static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs, bool with_padding, unsigned int header_bits,
+	CodingScheme cs, bool with_padding, unsigned int header_bits,
 	const unsigned int spb)
 {
 	unsigned int i;
-	unsigned int padding_bits = with_padding ? cs.optionalPaddingBits() : 0;
+	unsigned int padding_bits = with_padding ? mcs_opt_padding_bits(cs) : 0;
 
 	rlc->cs = cs;
 	rlc->r = 0;
@@ -330,7 +331,7 @@
 	rlc->es_p = 0;
 	rlc->rrbp = 0;
 	rlc->pr = 0;
-	rlc->num_data_blocks = num_data_blocks(cs.headerTypeData());
+	rlc->num_data_blocks = num_data_blocks(mcs_header_type(cs));
 	rlc->with_padding = with_padding;
 
 	OSMO_ASSERT(rlc->num_data_blocks <= ARRAY_SIZE(rlc->block_info));
@@ -341,35 +342,35 @@
 
 		rlc->data_offs_bits[i] =
 			header_bits + padding_bits +
-			(i+1) * num_data_block_header_bits(cs.headerTypeData()) +
+			(i+1) * num_data_block_header_bits(mcs_header_type(cs)) +
 			i * 8 * rlc->block_info[0].data_len;
 	}
 }
 
 void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs, bool with_padding, const unsigned int spb)
+	CodingScheme cs, bool with_padding, const unsigned int spb)
 {
 	return gprs_rlc_data_header_init(rlc, cs, with_padding,
-					 num_data_header_bits_DL(cs.headerTypeData()), spb);
+					 num_data_header_bits_DL(mcs_header_type(cs)), spb);
 }
 
 void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs, bool with_padding)
+	CodingScheme cs, bool with_padding)
 {
 	/*
 	 * last parameter is sent as 0 since common function used
 	 * for both DL and UL
 	 */
 	return gprs_rlc_data_header_init(rlc, cs, with_padding,
-					 num_data_header_bits_UL(cs.headerTypeData()), 0);
+					 num_data_header_bits_UL(mcs_header_type(cs)), 0);
 }
 
 void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
-	GprsCodingScheme cs, bool with_padding, const unsigned int spb)
+	CodingScheme cs, bool with_padding, const unsigned int spb)
 {
-	unsigned int data_len = cs.maxDataBlockBytes();
+	unsigned int data_len = mcs_max_data_block_bytes(cs);
 	if (with_padding)
-		data_len -= cs.optionalPaddingBits() / 8;
+		data_len -= mcs_opt_padding_bits(cs) / 8;
 
 	rdbi->data_len = data_len;
 	rdbi->bsn = 0;
@@ -380,19 +381,19 @@
 	rdbi->spb = spb;
 }
 
-unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs,
+unsigned int gprs_rlc_mcs_cps(CodingScheme cs,
 	enum egprs_puncturing_values punct,
 	enum egprs_puncturing_values punct2, bool with_padding)
 {
 	/* validate that punct and punct2 are as expected */
-	switch (CodingScheme(cs)) {
+	switch (cs) {
 	case MCS9:
 	case MCS8:
 	case MCS7:
 		if (punct2 == EGPRS_PS_INVALID) {
 			LOGP(DRLCMACDL, LOGL_ERROR,
 			     "Invalid punct2 value for coding scheme %d: %d\n",
-			     CodingScheme(cs), punct2);
+			     cs, punct2);
 			return -1;
 		}
 		/* fall through */
@@ -405,7 +406,7 @@
 		if (punct == EGPRS_PS_INVALID) {
 			LOGP(DRLCMACDL, LOGL_ERROR,
 			     "Invalid punct value for coding scheme %d: %d\n",
-			     CodingScheme(cs), punct);
+			     cs, punct);
 			return -1;
 		}
 		break;
@@ -414,7 +415,7 @@
 	}
 
 	/* See 3GPP TS 44.060 10.4.8a.3.1, 10.4.8a.2.1, 10.4.8a.1.1 */
-	switch (CodingScheme(cs)) {
+	switch (cs) {
 	case MCS1: return 0b1011 +
 		punct % EGPRS_MAX_PS_NUM_2;
 	case MCS2: return 0b1001 +
@@ -443,12 +444,12 @@
 }
 
 void gprs_rlc_mcs_cps_decode(unsigned int cps,
-	GprsCodingScheme cs, int *punct, int *punct2, int *with_padding)
+	CodingScheme cs, int *punct, int *punct2, int *with_padding)
 {
 	*punct2 = -1;
 	*with_padding = 0;
 
-	switch (CodingScheme(cs)) {
+	switch (cs) {
 	case MCS1:
 		cps -= 0b1011; *punct = cps % 2; break;
 	case MCS2:
@@ -481,8 +482,8 @@
  */
 enum egprs_puncturing_values gprs_get_punct_scheme(
 	enum egprs_puncturing_values punct,
-	const GprsCodingScheme &cs,
-	const GprsCodingScheme &cs_current,
+	const CodingScheme &cs,
+	const CodingScheme &cs_current,
 	const enum egprs_rlcmac_dl_spb spb)
 {
 
@@ -495,23 +496,23 @@
 		return punct;
 
 	/* TS  44.060 9.3.2.1.1 */
-	if ((CodingScheme(cs) == MCS9) &&
-	(CodingScheme(cs_current) == MCS6)) {
+	if ((cs == MCS9) &&
+	(cs_current == MCS6)) {
 		if ((punct == EGPRS_PS_1) || (punct == EGPRS_PS_3))
 			return EGPRS_PS_1;
 		else if (punct == EGPRS_PS_2)
 			return EGPRS_PS_2;
-	} else if ((CodingScheme(cs) == MCS6) &&
-	(CodingScheme(cs_current) == MCS9)) {
+	} else if ((cs == MCS6) &&
+	(cs_current == MCS9)) {
 		if (punct == EGPRS_PS_1)
 			return EGPRS_PS_3;
 		else if (punct == EGPRS_PS_2)
 			return EGPRS_PS_2;
-	} else if ((CodingScheme(cs) == MCS7) &&
-	(CodingScheme(cs_current) == MCS5))
+	} else if ((cs == MCS7) &&
+	(cs_current == MCS5))
 		return EGPRS_PS_1;
-	else if ((CodingScheme(cs) == MCS5) &&
-	(CodingScheme(cs_current) == MCS7))
+	else if ((cs == MCS5) &&
+	(cs_current == MCS7))
 		return EGPRS_PS_2;
 	else if (cs != cs_current)
 		return EGPRS_PS_1;
@@ -532,9 +533,9 @@
  * TS 44.060 10.4.8a.3.1, 10.4.8a.2.1, 10.4.8a.1.1
  */
 void gprs_update_punct_scheme(enum egprs_puncturing_values *punct,
-	const GprsCodingScheme &cs)
+	const CodingScheme &cs)
 {
-	switch (CodingScheme(cs)) {
+	switch (cs) {
 	case MCS1 :
 	case MCS2 :
 	case MCS5 :
diff --git a/src/rlc.h b/src/rlc.h
index 109c5b3..02ea437 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -19,7 +19,9 @@
  */
 #pragma once
 
-#include "gprs_coding_scheme.h"
+extern "C" {
+#include "coding_scheme.h"
+}
 
 #include <osmocom/core/endian.h>
 
@@ -154,7 +156,7 @@
 };
 
 struct gprs_rlc_data_info {
-	GprsCodingScheme cs;
+	CodingScheme cs;
 	unsigned int r;
 	unsigned int si;
 	unsigned int tfi;
@@ -192,15 +194,15 @@
 	 * 8.1.1.1 and Table 8.1.1.2
 	 * For UL. cs_last shall be used everywhere.
 	 */
-	GprsCodingScheme cs_current_trans;
-	GprsCodingScheme cs_last;
+	CodingScheme cs_current_trans;
+	CodingScheme cs_last;
 
 	/*
 	 * The MCS of initial transmission of a BSN
 	 * This variable is used for split block
 	 * processing in DL
 	 */
-	GprsCodingScheme cs_init;
+	CodingScheme cs_init;
 
 	/* puncturing scheme value to be used for next transmission*/
 	enum egprs_puncturing_values next_ps;
@@ -212,21 +214,21 @@
 uint8_t *prepare(struct gprs_rlc_data *rlc, size_t block_data_length);
 
 void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs, bool with_padding, const unsigned int spb);
+	CodingScheme cs, bool with_padding, const unsigned int spb);
 void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs, bool with_padding);
+	CodingScheme cs, bool with_padding);
 void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
-	GprsCodingScheme cs, bool with_padding, const unsigned int spb);
-unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, enum egprs_puncturing_values
+	CodingScheme cs, bool with_padding, const unsigned int spb);
+unsigned int gprs_rlc_mcs_cps(CodingScheme cs, enum egprs_puncturing_values
 	punct, enum egprs_puncturing_values punct2, bool with_padding);
-void gprs_rlc_mcs_cps_decode(unsigned int cps, GprsCodingScheme cs,
+void gprs_rlc_mcs_cps_decode(unsigned int cps, CodingScheme cs,
 	int *punct, int *punct2, int *with_padding);
 enum egprs_puncturing_values gprs_get_punct_scheme(enum egprs_puncturing_values
-	punct, const GprsCodingScheme &cs,
-	const GprsCodingScheme &cs_current_trans,
+	punct, const CodingScheme &cs,
+	const CodingScheme &cs_current_trans,
 	const enum egprs_rlcmac_dl_spb spb);
 void gprs_update_punct_scheme(enum egprs_puncturing_values *punct,
-	const GprsCodingScheme &cs);
+	const CodingScheme &cs);
 /*
  * I hold the currently transferred blocks and will provide
  * the routines to manipulate these arrays.
diff --git a/src/tbf.cpp b/src/tbf.cpp
index ccf257d..3726707 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -33,7 +33,6 @@
 #include <pcu_utils.h>
 #include <gprs_ms_storage.h>
 #include <sba.h>
-#include <gprs_coding_scheme.h>
 #include <gsm_timer.h>
 #include <pdch.h>
 
@@ -49,6 +48,7 @@
 #include <osmocom/gsm/protocol/gsm_04_08.h>
 
 #include "gsm_rlcmac.h"
+#include "coding_scheme.h"
 }
 
 #include <errno.h>
@@ -310,13 +310,14 @@
 	m_ms_class = ms_class_;
 }
 
-GprsCodingScheme gprs_rlcmac_tbf::current_cs() const
+CodingScheme gprs_rlcmac_tbf::current_cs() const
 {
-	GprsCodingScheme cs;
+	CodingScheme cs;
+
 	if (direction == GPRS_RLCMAC_UL_TBF)
-		cs = m_ms ? m_ms->current_cs_ul() : GprsCodingScheme();
+		cs = m_ms ? m_ms->current_cs_ul() : UNKNOWN;
 	else
-		cs = m_ms ? m_ms->current_cs_dl() : GprsCodingScheme();
+		cs = m_ms ? m_ms->current_cs_dl() : UNKNOWN;
 
 	return cs;
 }
@@ -965,8 +966,8 @@
 
 static void setup_egprs_mode(gprs_rlcmac_bts *bts, GprsMs *ms)
 {
-	if (mcs_is_edge_gmsk(GprsCodingScheme::getEgprsByNum(bts->max_mcs_ul)) &&
-		mcs_is_edge_gmsk(GprsCodingScheme::getEgprsByNum(bts->max_mcs_dl)) &&
+	if (mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts->max_mcs_ul)) &&
+		mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts->max_mcs_dl)) &&
 		ms->mode() != EGPRS)
 	{
 		ms->set_mode(EGPRS_GMSK);
diff --git a/src/tbf.h b/src/tbf.h
index 2b4cf6d..764c76f 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -24,14 +24,16 @@
 #include "rlc.h"
 #include "cxx_linuxlist.h"
 #include <gprs_debug.h>
-#include <gprs_coding_scheme.h>
 #include <gsm_timer.h>
 #include <stdint.h>
+
 extern "C" {
 #include <osmocom/core/utils.h>
-	#include <osmocom/core/linuxlist.h>
-	#include <osmocom/core/logging.h>
-	#include <osmocom/core/timer.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/timer.h>
+
+#include "coding_scheme.h"
 }
 
 struct bssgp_bvc_ctx;
@@ -245,7 +247,7 @@
 	void set_ta(uint8_t);
 	uint8_t ms_class() const;
 	void set_ms_class(uint8_t);
-	GprsCodingScheme current_cs() const;
+	CodingScheme current_cs() const;
 	size_t llc_queue_size() const;
 
 	time_t created_ts() const;
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index cd4ddb9..530ed04 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -30,7 +30,6 @@
 #include <gprs_codel.h>
 #include <decoding.h>
 #include <encoding.h>
-#include <gprs_coding_scheme.h>
 #include <gprs_ms.h>
 #include <gprs_ms_storage.h>
 #include <llc.h>
@@ -370,7 +369,7 @@
 {
 	int bsn;
 	int data_len2, force_data_len = -1;
-	GprsCodingScheme force_cs;
+	CodingScheme force_cs = UNKNOWN;
 
 	/* search for a nacked or resend marked bsn */
 	bsn = m_window.resend_needed();
@@ -446,7 +445,7 @@
 			return take_next_bsn(fn, previous_bsn, may_combine);
 	} else if (have_data()) {
 		/* The window has space left, generate new bsn */
-		GprsCodingScheme new_cs;
+		CodingScheme new_cs;
 		new_cs = force_cs ? force_cs : current_cs();
 		LOGPTBFDL(this, LOGL_DEBUG,
 			  "Sending new block at BSN %d, CS=%s\n",
@@ -480,7 +479,7 @@
 		bts->do_rate_ctr_inc(CTR_RLC_RESENT);
 	}
 
-	*may_combine = num_data_blocks(m_rlc.block(bsn)->cs_current_trans.headerTypeData()) > 1;
+	*may_combine = num_data_blocks(mcs_header_type(m_rlc.block(bsn)->cs_current_trans)) > 1;
 
 	return bsn;
 }
@@ -561,7 +560,7 @@
 	m_last_dl_drained_fn = -1;
 }
 
-int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, GprsCodingScheme cs)
+int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, CodingScheme cs)
 {
 	uint8_t *data;
 	gprs_rlc_data *rlc_data;
@@ -574,10 +573,10 @@
 	if (m_llc.frame_length() == 0)
 		schedule_next_frame();
 
-	OSMO_ASSERT(cs.isValid());
+	OSMO_ASSERT(mcs_is_valid(cs));
 
 	/* length of usable data block (single data unit w/o header) */
-	const uint8_t block_data_len = cs.maxDataBlockBytes();
+	const uint8_t block_data_len = mcs_max_data_block_bytes(cs);
 
 	/* now we still have untransmitted LLC data, so we fill mac block */
 	rlc_data = m_rlc.block(bsn);
@@ -691,7 +690,7 @@
 	int rc;
 	bool is_final = false;
 	gprs_rlc_data_info rlc;
-	GprsCodingScheme cs;
+	CodingScheme cs;
 	int bsns[ARRAY_SIZE(rlc.block_info)];
 	unsigned num_bsns;
 	bool need_padding = false;
@@ -740,8 +739,8 @@
 		 * Refer commit be881c028fc4da00c4046ecd9296727975c206a3
 		 * dated 2016-02-07 23:45:40 (UTC)
 		 */
-		if (cs != GprsCodingScheme(MCS8))
-			cs.decToSingleBlock(&need_padding);
+		if (cs != MCS8)
+			mcs_dec_to_single_block(&cs, &need_padding);
 	}
 
 	spb = get_egprs_dl_spb(index);
@@ -756,7 +755,7 @@
 	rlc.tfi = m_tfi; /* TFI */
 
 	/* return data block(s) as message */
-	msg_len = cs.sizeDL();
+	msg_len = mcs_size_dl(cs);
 	dl_msg = msgb_alloc(msg_len, "rlcmac_dl_data");
 	if (!dl_msg)
 		return NULL;
@@ -1273,11 +1272,11 @@
 	egprs_rlc_dl_reseg_bsn_state *block_status_dl =
 				&rlc_data->spb_status.block_status_dl;
 
-	enum CodingScheme cs_init = CodingScheme(rlc_data->cs_init);
-	enum CodingScheme cs_current_trans = CodingScheme(rlc_data->cs_current_trans);
+	enum CodingScheme cs_init = rlc_data->cs_init;
+	enum CodingScheme cs_current_trans = rlc_data->cs_current_trans;
 
-	enum HeaderType ht_cs_init = rlc_data->cs_init.headerTypeData();
-	enum HeaderType ht_cs_current_trans = rlc_data->cs_current_trans.headerTypeData();
+	enum HeaderType ht_cs_init = mcs_header_type(rlc_data->cs_init);
+	enum HeaderType ht_cs_current_trans = mcs_header_type(rlc_data->cs_current_trans);
 
 	*block_data = &rlc_data->block[0];
 
@@ -1346,11 +1345,11 @@
 	struct gprs_rlc_data *rlc_data = m_rlc.block(bsn);
 	egprs_rlc_dl_reseg_bsn_state block_status_dl = rlc_data->spb_status.block_status_dl;
 
-	enum CodingScheme cs_init = CodingScheme(rlc_data->cs_init);
-	enum CodingScheme cs_current_trans = CodingScheme(rlc_data->cs_current_trans);
+	enum CodingScheme cs_init = rlc_data->cs_init;
+	enum CodingScheme cs_current_trans = rlc_data->cs_current_trans;
 
-	enum HeaderType ht_cs_init = rlc_data->cs_init.headerTypeData();
-	enum HeaderType ht_cs_current_trans = rlc_data->cs_current_trans.headerTypeData();
+	enum HeaderType ht_cs_init = mcs_header_type(rlc_data->cs_init);
+	enum HeaderType ht_cs_current_trans = mcs_header_type(rlc_data->cs_current_trans);
 
 	/* Table 10.4.8b.1 of 44.060 */
 	if (ht_cs_current_trans == HEADER_EGPRS_DATA_TYPE_3) {
diff --git a/src/tbf_dl.h b/src/tbf_dl.h
index f3838d7..2da0ec1 100644
--- a/src/tbf_dl.h
+++ b/src/tbf_dl.h
@@ -111,7 +111,7 @@
 	int take_next_bsn(uint32_t fn, int previous_bsn,
 		bool *may_combine);
 	bool restart_bsn_cycle();
-	int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
+	int create_new_bsn(const uint32_t fn, CodingScheme cs);
 	struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
 					int index, int index2 = -1);
 	int update_window(const uint8_t ssn, const uint8_t *rbb);
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index 9899580..0cc60f3 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -29,7 +29,6 @@
 #include <gprs_bssgp_pcu.h>
 #include <decoding.h>
 #include <pcu_l1_if.h>
-#include <gprs_coding_scheme.h>
 #include <gprs_ms.h>
 #include <llc.h>
 #include "pcu_utils.h"
@@ -75,7 +74,7 @@
 	const uint8_t *data = _data->block;
 	uint8_t len = _data->len;
 	const struct gprs_rlc_data_block_info *rdbi = &_data->block_info;
-	GprsCodingScheme cs = _data->cs_last;
+	CodingScheme cs = _data->cs_last;
 
 	Decoding::RlcData frames[16], *frame;
 	int i, num_frames = 0;
diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp
index 3f424d1..4f5fb5d 100644
--- a/tests/edge/EdgeTest.cpp
+++ b/tests/edge/EdgeTest.cpp
@@ -21,7 +21,6 @@
  */
 
 #include "gprs_debug.h"
-#include "gprs_coding_scheme.h"
 #include "decoding.h"
 #include "encoding.h"
 #include "rlc.h"
@@ -31,6 +30,7 @@
 
 extern "C" {
 #include "pcu_vty.h"
+#include "coding_scheme.h"
 
 #include <osmocom/core/application.h>
 #include <osmocom/core/msgb.h>
@@ -48,69 +48,69 @@
 int16_t spoof_mnc = 0, spoof_mcc = 0;
 bool spoof_mnc_3_digits = false;
 
-static void check_coding_scheme(GprsCodingScheme& cs, enum mcs_kind mode)
+static void check_coding_scheme(CodingScheme& cs, enum mcs_kind mode)
 {
 	volatile unsigned expected_size;
 	bool need_padding;
-	GprsCodingScheme new_cs;
+	CodingScheme new_cs;
 
-	OSMO_ASSERT(cs.isValid());
-	OSMO_ASSERT(cs.isCompatible(mode));
+	OSMO_ASSERT(mcs_is_valid(cs));
+	OSMO_ASSERT(mcs_is_compat_kind(cs, mode));
 
 	/* Check static getBySizeUL() */
-	expected_size = cs.usedSizeUL();
-	if (cs.spareBitsUL() > 0 && mcs_is_gprs(cs))
+	expected_size = mcs_used_size_ul(cs);
+	if (mcs_spare_bits_ul(cs) > 0 && mcs_is_gprs(cs))
 		expected_size += 1;
-	OSMO_ASSERT(expected_size == cs.sizeUL());
-	OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
+	OSMO_ASSERT(expected_size == mcs_size_ul(cs));
+	OSMO_ASSERT(cs == mcs_get_by_size_ul(expected_size));
 
 	/* Check static sizeUL() */
-	expected_size = cs.usedSizeDL();
-	if (cs.spareBitsDL() > 0 && mcs_is_gprs(cs))
+	expected_size = mcs_used_size_dl(cs);
+	if (mcs_spare_bits_dl(cs) > 0 && mcs_is_gprs(cs))
 		expected_size += 1;
-	OSMO_ASSERT(expected_size == cs.sizeDL());
+	OSMO_ASSERT(expected_size == mcs_size_dl(cs));
 
 	/* Check data block sizes */
-	OSMO_ASSERT(cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData()) < cs.maxBytesDL());
-	OSMO_ASSERT(cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData()) < cs.maxBytesUL());
+	OSMO_ASSERT(mcs_max_data_block_bytes(cs) * num_data_blocks(mcs_header_type(cs)) < mcs_max_bytes_dl(cs));
+	OSMO_ASSERT(mcs_max_data_block_bytes(cs) * num_data_blocks(mcs_header_type(cs)) < mcs_max_bytes_ul(cs));
 
 	/* Check inc/dec */
 	new_cs = cs;
-	new_cs.inc(mode);
-	OSMO_ASSERT(new_cs.isCompatible(mode));
+	mcs_inc_kind(&new_cs, mode);
+	OSMO_ASSERT(mcs_is_compat_kind(new_cs, mode));
 	if (new_cs != cs) {
-		new_cs.dec(mode);
-		OSMO_ASSERT(new_cs.isCompatible(mode));
+		mcs_dec_kind(&new_cs, mode);
+		OSMO_ASSERT(mcs_is_compat_kind(new_cs, mode));
 		OSMO_ASSERT(new_cs == cs);
 	}
-	new_cs.dec(mode);
-	OSMO_ASSERT(new_cs.isCompatible(mode));
+	mcs_dec_kind(&new_cs, mode);
+	OSMO_ASSERT(mcs_is_compat_kind(new_cs, mode));
 	if (new_cs != cs) {
-		new_cs.inc(mode);
-		OSMO_ASSERT(new_cs.isCompatible(mode));
+		mcs_inc_kind(&new_cs, mode);
+		OSMO_ASSERT(mcs_is_compat_kind(new_cs, mode));
 		OSMO_ASSERT(new_cs == cs);
 	}
 
 	new_cs = cs;
-	new_cs.decToSingleBlock(&need_padding);
-	OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
-	OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
-	OSMO_ASSERT(cs.isCompatible(new_cs));
+	mcs_dec_to_single_block(&new_cs, &need_padding);
+	OSMO_ASSERT(mcs_is_family_compat(new_cs, cs));
+	OSMO_ASSERT(mcs_is_family_compat(cs, new_cs));
+	OSMO_ASSERT(mcs_is_compat(cs, new_cs));
 	if (need_padding) {
-		OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
-			new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
+		OSMO_ASSERT(mcs_max_data_block_bytes(new_cs) ==
+			mcs_opt_padding_bits(new_cs)/8 + mcs_max_data_block_bytes(cs));
 	} else {
-		OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
+		OSMO_ASSERT(mcs_max_data_block_bytes(new_cs) == mcs_max_data_block_bytes(cs));
 	}
 
 }
 
-static bool check_strong_monotonicity(const GprsCodingScheme *cs, uint8_t last_UL, uint8_t last_DL)
+static bool check_strong_monotonicity(const CodingScheme cs, uint8_t last_UL, uint8_t last_DL)
 {
-	if (cs->maxBytesUL() <= last_UL)
+	if (mcs_max_bytes_ul(cs) <= last_UL)
 		return false;
 
-	if (cs->maxBytesDL() <= last_DL)
+	if (mcs_max_bytes_dl(cs) <= last_DL)
 		return false;
 
 	return true;
@@ -144,31 +144,28 @@
 
 	printf("=== start %s ===\n", __func__);
 
-	GprsCodingScheme cs;
+	CodingScheme cs = UNKNOWN;
 	OSMO_ASSERT(!cs);
-	OSMO_ASSERT(CodingScheme(cs) == UNKNOWN);
-	OSMO_ASSERT(cs == GprsCodingScheme(UNKNOWN));
-	OSMO_ASSERT(!cs.isCompatible(GPRS));
-	OSMO_ASSERT(!cs.isCompatible(EGPRS_GMSK));
-	OSMO_ASSERT(!cs.isCompatible(EGPRS));
+	OSMO_ASSERT(!mcs_is_compat_kind(cs, GPRS));
+	OSMO_ASSERT(!mcs_is_compat_kind(cs, EGPRS_GMSK));
+	OSMO_ASSERT(!mcs_is_compat_kind(cs, EGPRS));
 
 	last_size_UL = 0;
 	last_size_DL = 0;
 
 	for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
-		GprsCodingScheme current_cs(gprs_schemes[i]);
+		CodingScheme current_cs = gprs_schemes[i];
 		OSMO_ASSERT(mcs_is_gprs(current_cs));
 		OSMO_ASSERT(!mcs_is_edge(current_cs));
 		OSMO_ASSERT(!mcs_is_edge_gmsk(current_cs));
-		OSMO_ASSERT(CodingScheme(current_cs) == gprs_schemes[i]);
-		OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
+		OSMO_ASSERT(current_cs == gprs_schemes[i]);
 
-		OSMO_ASSERT(check_strong_monotonicity(&current_cs, last_size_UL, last_size_DL));
-		last_size_UL = current_cs.maxBytesUL();
-		last_size_DL = current_cs.maxBytesDL();
+		OSMO_ASSERT(check_strong_monotonicity(current_cs, last_size_UL, last_size_DL));
+		last_size_UL = mcs_max_bytes_ul(current_cs);
+		last_size_DL = mcs_max_bytes_dl(current_cs);
 
 		/* Check header types */
-		OSMO_ASSERT(current_cs.headerTypeData() == HEADER_GPRS_DATA);
+		OSMO_ASSERT(mcs_header_type(current_cs) == HEADER_GPRS_DATA);
 
 		check_coding_scheme(current_cs, GPRS);
 	}
@@ -178,16 +175,15 @@
 	last_size_DL = 0;
 
 	for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
-		GprsCodingScheme current_cs(egprs_schemes[i].s);
+		CodingScheme current_cs = egprs_schemes[i].s;
 		OSMO_ASSERT(!mcs_is_gprs(current_cs));
 		OSMO_ASSERT(mcs_is_edge(current_cs));
 		OSMO_ASSERT(mcs_is_edge_gmsk(current_cs) == !!egprs_schemes[i].is_gmsk);
-		OSMO_ASSERT(CodingScheme(current_cs) == egprs_schemes[i].s);
-		OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
+		OSMO_ASSERT(current_cs == egprs_schemes[i].s);
 
-		OSMO_ASSERT(check_strong_monotonicity(&current_cs, last_size_UL, last_size_DL));
-		last_size_UL = current_cs.maxBytesUL();
-		last_size_DL = current_cs.maxBytesDL();
+		OSMO_ASSERT(check_strong_monotonicity(current_cs, last_size_UL, last_size_DL));
+		last_size_UL = mcs_max_bytes_ul(current_cs);
+		last_size_DL = mcs_max_bytes_dl(current_cs);
 
 		if (egprs_schemes[i].is_gmsk)
 			check_coding_scheme(current_cs, EGPRS_GMSK);
@@ -201,7 +197,7 @@
 static void test_rlc_unit_decoder()
 {
 	struct gprs_rlc_data_block_info rdbi = {0};
-	GprsCodingScheme cs;
+	CodingScheme cs;
 	uint8_t data[74];
 	Decoding::RlcData chunks[16];
 	volatile int num_chunks = 0;
@@ -213,7 +209,7 @@
 
 	/* TS 44.060, B.1 */
 	cs = CS4;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 0;
 	rdbi.cv = 15;
@@ -232,12 +228,12 @@
 	OSMO_ASSERT(chunks[1].length == 26);
 	OSMO_ASSERT(chunks[1].is_complete);
 	OSMO_ASSERT(chunks[2].offset == 39);
-	OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
+	OSMO_ASSERT(chunks[2].length == mcs_max_data_block_bytes(cs) - 39);
 	OSMO_ASSERT(!chunks[2].is_complete);
 
 	/* TS 44.060, B.2 */
 	cs = CS1;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 0;
 	rdbi.cv = 15;
@@ -271,7 +267,7 @@
 
 	/* TS 44.060, B.3 */
 	cs = CS1;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 0;
 	rdbi.cv = 15;
@@ -292,7 +288,7 @@
 
 	/* TS 44.060, B.4 */
 	cs = CS1;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 1;
 	rdbi.ti = 0;
 	rdbi.cv = 15;
@@ -308,7 +304,7 @@
 
 	/* TS 44.060, B.6 */
 	cs = CS1;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 1;
 	rdbi.ti = 0;
 	rdbi.cv = 0;
@@ -324,7 +320,7 @@
 
 	/* TS 44.060, B.8.1 */
 	cs = MCS4;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 0;
 	rdbi.cv = 15;
@@ -353,7 +349,7 @@
 	 * is not consistent with Section 10.3a.1 & 10.3a.2. */
 
 	cs = MCS2;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 0;
 	rdbi.cv = 15;
@@ -417,7 +413,7 @@
 	/* Note that the spec confuses the byte numbering here, too (see above) */
 
 	cs = MCS2;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 1;
 	rdbi.ti = 0;
 	rdbi.cv = 0;
@@ -433,7 +429,7 @@
 
 	/* CS-1, TLLI, last block, single chunk until the end of the block */
 	cs = CS1;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 1;
 	rdbi.ti = 1;
 	rdbi.cv = 0;
@@ -454,7 +450,7 @@
 
 	/* Like TS 44.060, B.2, first RLC block but with TLLI */
 	cs = CS1;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 1;
 	rdbi.cv = 15;
@@ -476,7 +472,7 @@
 
 	/* Like TS 44.060, B.8.1 but with TLLI */
 	cs = MCS4;
-	rdbi.data_len = cs.maxDataBlockBytes();
+	rdbi.data_len = mcs_max_data_block_bytes(cs);
 	rdbi.e = 0;
 	rdbi.ti = 1;
 	rdbi.cv = 15;
@@ -528,7 +524,7 @@
 static void test_rlc_unit_encoder()
 {
 	struct gprs_rlc_data_block_info rdbi = {0};
-	GprsCodingScheme cs;
+	CodingScheme cs;
 	uint8_t data[74];
 	uint8_t llc_data[1500] = {0,};
 	int num_chunks = 0;
@@ -1088,17 +1084,17 @@
 		scheme < NUM_SCHEMES;
 		scheme = CodingScheme(scheme + 1))
 	{
-		GprsCodingScheme cs(scheme);
+		CodingScheme cs(scheme);
 
 		for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
 			/* prepare test block */
 			test_block[0] = pattern ^ 0xff;
-			for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
+			for (i = 1; i + 1 < mcs_max_data_block_bytes(cs); i++)
 				test_block[i] = i;
-			test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
+			test_block[mcs_max_data_block_bytes(cs)-1] = pattern ^ 0xff;
 
 			for (block_idx = 0;
-				block_idx < num_data_blocks(cs.headerTypeData());
+				block_idx < num_data_blocks(mcs_header_type(cs));
 				block_idx++)
 			{
 				struct gprs_rlc_data_info rlc;
@@ -1110,7 +1106,7 @@
 
 				fprintf(stderr,
 					"Test data block: %s\n",
-					osmo_hexdump(test_block, cs.maxDataBlockBytes()));
+					osmo_hexdump(test_block, mcs_max_data_block_bytes(cs)));
 
 				Encoding::rlc_copy_from_aligned_buffer(
 					&rlc, block_idx, bits, test_block);
@@ -1119,20 +1115,20 @@
 					"Encoded message block, %s, idx %d, "
 					"pattern %02x: %s\n",
 					mcs_name(rlc.cs), block_idx, pattern,
-					osmo_hexdump(bits, cs.sizeDL()));
+					osmo_hexdump(bits, mcs_size_dl(cs)));
 
 				Decoding::rlc_copy_to_aligned_buffer(
 					&rlc, block_idx, bits, out_block);
 
 				fprintf(stderr,
 					"Out data block: %s\n",
-					osmo_hexdump(out_block, cs.maxDataBlockBytes()));
+					osmo_hexdump(out_block, mcs_max_data_block_bytes(cs)));
 				/* restore original bits */
 				Encoding::rlc_copy_from_aligned_buffer(
 					&rlc, block_idx, bits, saved_block);
 
 				OSMO_ASSERT(memcmp(test_block, out_block,
-						rlc.cs.maxDataBlockBytes()) == 0);
+						mcs_max_data_block_bytes(rlc.cs)) == 0);
 
 				for (i = 0; i < sizeof(bits); i++)
 					OSMO_ASSERT(bits[i] == pattern);
@@ -1147,13 +1143,13 @@
 
 	printf("=== start %s ===\n", __func__);
 	gprs_rlc_data_info_init_dl(&rlc,
-			GprsCodingScheme(CS1), false, 0);
+			CodingScheme(CS1), false, 0);
 	OSMO_ASSERT(rlc.num_data_blocks == 1);
 	OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
 	OSMO_ASSERT(rlc.block_info[0].data_len == 20);
 
 	gprs_rlc_data_info_init_dl(&rlc,
-			GprsCodingScheme(MCS1), false, 0);
+			CodingScheme(MCS1), false, 0);
 	OSMO_ASSERT(rlc.num_data_blocks == 1);
 	OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
 	OSMO_ASSERT(rlc.block_info[0].data_len == 22);
@@ -1188,7 +1184,7 @@
 	tfi = 1;
 
 	struct gprs_rlc_data_info rlc;
-	GprsCodingScheme cs;
+	CodingScheme cs;
 	int rc, offs;
 
 	/*without padding*/
@@ -1289,7 +1285,7 @@
 	uint8_t data[155] = {0};
 	struct gprs_rlc_ul_header_egprs_1 *egprs1  = NULL;
 	struct gprs_rlc_data_info rlc;
-	GprsCodingScheme cs;
+	CodingScheme cs;
 	int rc;
 
 	egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index 36f9ced..f934c6c 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -32,6 +32,7 @@
 
 extern "C" {
 #include "pcu_vty.h"
+#include "coding_scheme.h"
 
 #include <osmocom/core/application.h>
 #include <osmocom/core/msgb.h>
@@ -656,7 +657,6 @@
 	gprs_rlcmac_bts *bts;
 	RlcMacUplink_t ulreq = {0};
 	struct gprs_rlc_ul_header_egprs_3 *egprs3  = NULL;
-	GprsCodingScheme cs;
 
 	bts = the_bts->bts_data();
 
@@ -732,7 +732,6 @@
 	 * TS 44.060, B.8.1
 	 * first seg received first, later second seg
 	 */
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 0;
 	egprs3->r = 1;
@@ -805,7 +804,6 @@
 	gprs_rlcmac_bts *bts;
 	RlcMacUplink_t ulreq = {0};
 	struct gprs_rlc_ul_header_egprs_3 *egprs3  = NULL;
-	GprsCodingScheme cs;
 
 	bts = the_bts->bts_data();
 
@@ -882,7 +880,6 @@
 	 * TS 44.060, B.8.1
 	 * first seg received first, later second seg
 	 */
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -937,7 +934,6 @@
 	 */
 	memset(data_msg, 0, sizeof(data_msg));
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -990,7 +986,6 @@
 	 * TS 44.060, B.8.1
 	 * Error scenario with spb as 1
 	 */
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1027,7 +1022,6 @@
 	for (i = 0; i < 42; i++)
 		data_msg[i] = i;
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1051,7 +1045,6 @@
 	OSMO_ASSERT(block->spb_status.block_status_ul ==
 				EGPRS_RESEG_FIRST_SEG_RXD);
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1079,7 +1072,6 @@
 	OSMO_ASSERT(block->cs_last ==
 			MCS6);
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1103,7 +1095,6 @@
 	OSMO_ASSERT(block->spb_status.block_status_ul ==
 				EGPRS_RESEG_FIRST_SEG_RXD);
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1127,7 +1118,6 @@
 	OSMO_ASSERT(block->spb_status.block_status_ul ==
 				EGPRS_RESEG_FIRST_SEG_RXD);
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1155,7 +1145,6 @@
 	/* Assembled MCS is MCS6. so the size is 74 */
 	OSMO_ASSERT(block->len == 74);
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1179,7 +1168,6 @@
 	OSMO_ASSERT(block->spb_status.block_status_ul ==
 				EGPRS_RESEG_SECOND_SEG_RXD);
 
-	cs = MCS3;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 1;
 	egprs3->r = 1;
@@ -1251,7 +1239,6 @@
 	gprs_rlcmac_ul_tbf *ul_tbf;
 	gprs_rlcmac_bts *bts;
 	RlcMacUplink_t ulreq = {0};
-	GprsCodingScheme cs;
 
 	bts = the_bts->bts_data();
 
@@ -1318,8 +1305,6 @@
 	uint8_t trx_no = 0;
 	int tfi = 0;
 	struct gprs_rlcmac_pdch *pdch;
-	GprsCodingScheme cs;
-
 
 	/* send fake data with cv=0*/
 	struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL;
@@ -1400,7 +1385,6 @@
 	uint8_t trx_no = 0;
 	int tfi = 0;
 	struct gprs_rlcmac_pdch *pdch;
-	GprsCodingScheme cs;
 
 	check_tbf(ul_tbf);
 	/* send fake data with cv=0*/
@@ -1482,8 +1466,6 @@
 	int tfi = 0;
 	gprs_rlcmac_ul_tbf *ul_tbf;
 	struct gprs_rlcmac_pdch *pdch;
-	GprsCodingScheme cs;
-
 
 	/* check the TBF */
 	ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no);
@@ -2363,7 +2345,6 @@
 	gprs_rlcmac_bts *bts;
 	RlcMacUplink_t ulreq = {0};
 	struct gprs_rlc_ul_header_egprs_3 *egprs3  = NULL;
-	GprsCodingScheme cs;
 	Packet_Resource_Request_t *presreq = NULL;
 	MS_Radio_Access_capability_t *pmsradiocap = NULL;
 	Multislot_capability_t *pmultislotcap = NULL;
@@ -2428,7 +2409,6 @@
 	OSMO_ASSERT(ms->ta() == qta/4);
 	OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
 
-	cs = MCS4;
 	egprs3 = (struct gprs_rlc_ul_header_egprs_3 *) data_msg;
 	egprs3->si = 0;
 	egprs3->r = 1;

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

Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: Ie9ce2144ba9e8dbba9704d4e0000a2929e3e41df
Gerrit-Change-Number: 18351
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200518/d7cb028c/attachment.htm>


More information about the gerrit-log mailing list