library: Initial work on GPRS RLC/MAC encoder/decoder

For Downlink and Uplink RLC/MAC Control blocks this is already working
quite nicely.  Data blocks is not working, as their encoding cannot be
expressed in TTCN-3 RAW syntax, and a mixture of C++/native and
RAW-generated coder will be required.
diff --git a/library/RLCMAC_Types.ttcn b/library/RLCMAC_Types.ttcn
new file mode 100644
index 0000000..f73721c
--- /dev/null
+++ b/library/RLCMAC_Types.ttcn
@@ -0,0 +1,200 @@
+/* TITAN REW encode/decode definitions for 3GPP TS 44.060 RLC/MAC Blocks */
+module RLCMAC_Types {
+	import from General_Types all;
+	import from Osmocom_Types all;
+	import from GSM_Types all;
+
+	/* TS 44.060 10.4.7 */
+	type enumerated MacPayloadType {
+		MAC_PT_RLC_DATA			('00'B),
+		MAC_PT_RLCMAC_NO_OPT		('01'B),
+		MAC_PT_RLCMAC_OPT		('10'B),
+		MAC_PT_RESERVED			('11'B)
+	} with { variant "FIELDLENGTH(2)" };
+
+	/* TS 44.060 10.4.5 */
+	type enumerated MacRrbp {
+		RRBP_Nplus13_mod_2715648	('00'B),
+		RRBP_Nplus17_or_18_mod_2715648	('01'B),
+		RRBP_Nplus22_or_22_mod_2715648	('10'B),
+		RRBP_Nplus26_mod_2715648	('11'B)
+	} with { variant "FIELDLENGTH(2)" };
+
+	/* Partof DL RLC data block and DL RLC/MAC ctrl block */
+	type record DlMacHeader {
+		MacPayloadType	payload_type,
+		MacRrbp		rrbp,
+		boolean		rrbp_valid,
+		uint3_t		usf
+	} with {
+		variant (rrbp_valid) "FIELDLENGTH(1)"
+	};
+
+	/* TS 44.060 10.4.10a */
+	type enumerated PowerReduction {
+		PWR_RED_0_to_3dB		('00'B),
+		PWR_RED_3_to_7dB		('01'B),
+		PWR_RED_7_to_10dB		('10'B),
+		PWR_RED_RESERVED		('11'B)
+	} with { variant "FIELDLENGTH(2)" };
+
+	/* TS 44.060 10.4.9d */
+	type enumerated DirectionBit {
+		DIR_UPLINK_TBF		('0'B),
+		DIR_DOWNLINK_TBF	('1'B)
+	} with { variant "FIELDLENGTH(1)" };
+
+	type record TfiOctet {
+		/* PR, TFI, D */
+		PowerReduction	pr,
+		uint5_t		tfi,
+		DirectionBit	d
+	} with { variant "" };
+
+	type record RbsnExtOctet {
+		uint3_t		rbsn_e,
+		BIT1		fs_e,
+		BIT4		spare
+	} with { variant "" };
+
+	type record DlCtrlOptOctets {
+		/* RBSN, RTI, FS, AC (optional, depending on mac_hdr.payload_type) */
+		BIT1		rbsn,
+		uint5_t		rti,
+		boolean		fs,
+		boolean		tfi_octet_present,
+		TfiOctet	tfi optional,
+		RbsnExtOctet	rbsn_ext optional
+	} with {
+		variant (fs) "FIELDLENGTH(1)"
+		variant (tfi_octet_present) "FIELDLENGTH(1)"
+		variant (tfi) "PRESENCE(tfi_octet_present = true)"
+		variant (rbsn_ext) "PRESENCE(rbsn='1'B, fs=false)"
+	};
+
+	/* TS 44.060 10.3.1 Downlink RLC/MAC control block */
+	type record RlcmacDlCtrlBlock {
+		DlMacHeader		mac_hdr,
+		DlCtrlOptOctets		opt optional,
+		octetstring		payload
+	} with {
+		variant (opt) "PRESENCE(mac_hdr.payload_type = MAC_PT_RLCMAC_OPT)"
+	};
+
+	external function enc_RlcmacDlCtrlBlock(in RlcmacDlCtrlBlock si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_RlcmacDlCtrlBlock(in octetstring stream) return RlcmacDlCtrlBlock
+		with { extension "prototype(convert) decode(RAW)" };
+
+	type record UlMacCtrlHeader {
+		MacPayloadType		pt,
+		BIT5			spare,
+		boolean			retry
+	} with { variant (retry) "FIELDLENGTH(1)" };
+
+	/* TS 44.060 10.3.2 UplinkRLC/MAC control block */
+	type record RlcmacUlCtrlBlock {
+		UlMacCtrlHeader		mac_hdr,
+		octetstring		payload
+	} with { variant "" };
+
+	external function enc_RlcmacUlCtrlBlock(in RlcmacUlCtrlBlock si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_RlcmacUlCtrlBlock(in octetstring stream) return RlcmacUlCtrlBlock
+		with { extension "prototype(convert) decode(RAW)" };
+
+	/* a single RLC block / LLC-segment */
+
+	type record RlcBlockHdr {
+		uint6_t		length_ind,
+		/* 1 = new LLC PDU starts */
+		BIT1		more,
+		/* 0 = another extension octet after LLC PDU, 1 = no more extension octets */
+		BIT1		e
+	} with { variant "" };
+
+	type record RlcBlock {
+		uint6_t		length_ind,
+		BIT1		more,
+		BIT1		e,
+		octetstring 	rlc optional
+	} with {
+		variant (rlc) "PRESENCE (more = '1'B)"
+		variant (length_ind) "LENGTHTO(length_ind, more, e, rlc)"
+	};
+
+	type record of RlcBlock RlcBlocks;
+
+	/* TS 44.060 10.2.1 Downlink RLC data block */
+	type record RlcmacDlDataBlock {
+		/* Octet 1 */
+		DlMacHeader		mac_hdr,
+		/* Octet 2 */
+		PowerReduction		pr,
+		BIT1			spare,
+		uint4_t			tfi, /* 3 or 4? */
+		boolean			fbi,
+		/* Octet 3 */
+		uint7_t			bsn,
+		BIT1			e ('1'B),
+		RlcBlocks		rlc_blocks
+	} with { variant "" };
+
+	external function enc_RlcmacDlDataBlock(in RlcmacDlDataBlock si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_RlcmacDlDataBlock(in octetstring stream) return RlcmacDlDataBlock
+		with { extension "prototype(convert) decode(RAW)" };
+
+
+	/* TS 44.060 10.2.2 */
+	type record UlMacDataHeader {
+		MacPayloadType		pt,
+		uint4_t			countdown,
+		boolean			stall_ind,
+		boolean			retry
+	} with {
+		variant (stall_ind) "FIELDLENGTH(1)"
+		variant (retry) "FIELDLENGTH(1)"
+	};
+
+	type record RlcMacUlTlli {
+		RlcBlockHdr		hdr,
+		uint32_t		tlli
+	} with {
+		variant ""
+	}
+
+	type record RlcMacUlPfi {
+		uint7_t			pfi,
+		boolean			m
+	} with {
+		variant (m) "FIELDLENGTH(1)"
+	};
+
+	/* TS 44.060 10.2.2 */
+	type record RlcmacUlDataBlock {
+		/* MAC header */
+		UlMacDataHeader		mac_hdr,
+		/* Octet 1 */
+		BIT1			spare,
+		boolean			pfi_ind,
+		uint5_t			tfi,
+		boolean			tlli_ind,
+		/* Octet 2 */
+		uint7_t			bsn,
+		BIT1			e ('1'B),
+		/* Octet 3 (optional) */
+		RlcMacUlTlli		tlli,
+		RlcMacUlPfi		pfi,
+		RlcBlocks		blocks
+	} with {
+		variant (tlli) "PRESENCE(tlli_ind = true)"
+		variant (pfi) "PRESENCE(pfi_ind = true)"
+	};
+
+	external function enc_RlcmacUlDataBlock(in RlcmacUlDataBlock si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_RlcmacUlDataBlock(in octetstring stream) return RlcmacUlDataBlock
+		with { extension "prototype(convert) decode(RAW)" };
+
+} with { encode "RAW"; variant "FIELDORDER(msb)" }