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/GSM_SystemInformation.ttcn b/library/GSM_SystemInformation.ttcn
index 74852d4..90fa425 100644
--- a/library/GSM_SystemInformation.ttcn
+++ b/library/GSM_SystemInformation.ttcn
@@ -15,7 +15,7 @@
 	} with { variant "" };
 
 	/* 24.008 10.5.1.1 */
-	type uint16_t CellIdentity;
+	type uint16_t SysinfoCellIdentity;
 
 	/* 44.018 10.5.2.1b */
 	type octetstring CellChannelDescription with { variant "FIELDLENGTH(16)" };
@@ -117,7 +117,7 @@
 
 	/* 44.018 9.1.35 */
 	type record SystemInformationType3 {
-		CellIdentity			cell_id,
+		SysinfoCellIdentity		cell_id,
 		LocationAreaIdentification	lai,
 		ControlChannelDescription	ctrl_chan_desc,
 		CellOptions			cell_options,
@@ -164,7 +164,7 @@
 
 	/* 44.018 9.1.40 */
 	type record SystemInformationType6 {
-		CellIdentity			cell_id,
+		SysinfoCellIdentity		cell_id,
 		LocationAreaIdentification	lai,
 		CellOptionsSacch		cell_options,
 		BIT8				ncc_permitted,
diff --git a/library/GSM_Types.ttcn b/library/GSM_Types.ttcn
index c205140..7275101 100644
--- a/library/GSM_Types.ttcn
+++ b/library/GSM_Types.ttcn
@@ -16,6 +16,7 @@
 	type integer GsmRxLev (0..63);
 	type integer GsmTsc (0..7) with { variant "FIELDLENGTH(8)" };
 	type uint32_t GsmTmsi;
+	type uint32_t GprsTlli;
 
 	/* Table 10.4.1 of Section 10.4 / 3GPP TS 44.018 */
 	type enumerated RrMessageType {
@@ -149,6 +150,9 @@
 	type record MaioHsn {
 	} with { variant "" };
 
+	/* TS 24.008 10.5.1.1 */
+	type uint16_t CellIdentity;
+
 	/* TS 24.008 10.5.1.2 */
 	type uint4_t CipheringKeySeqNr (0..7);
 
@@ -335,6 +339,21 @@
 		boolean	ps_ir
 	} with { variant "" };
 
+	/* 24.008 10.5.5.6 */
+	type record DrxParameter {
+		uint8_t		split_pg_cycle_code,
+		uint4_t		drx_cycle_len_coeff,
+		boolean		split_on_ccch,
+		uint3_t		non_drx_timer
+	} with { variant "" };
+
+	/* 24.008 10.5.5.15 */
+	type record RoutingAreaIdentification {
+		LocationAreaIdentification	lai,
+		uint8_t				rac
+	} with { variant "" };
+
+
 
 	/* 9.1.18 */
 	type record ImmediateAssignment {
diff --git a/library/Osmocom_Types.ttcn b/library/Osmocom_Types.ttcn
index 0c26f02..484f6d1 100644
--- a/library/Osmocom_Types.ttcn
+++ b/library/Osmocom_Types.ttcn
@@ -1,6 +1,7 @@
 module Osmocom_Types {
 	type integer uint8_t (0..255) with { variant "unsigned 8 bit" };
 	type integer uint16_t (0..65535) with { variant "unsigned 16 bit" };
+	type integer uint24_t (0..16777215) with { variant "unsigned 24 bit" };
 	type integer uint32_t (0..4294967295) with { variant "unsigned 32 bit" };
 
 	type integer int8_t (-128..127) with { variant "8 bit" };
diff --git a/library/RLCMAC_CSN1_Types.ttcn b/library/RLCMAC_CSN1_Types.ttcn
new file mode 100644
index 0000000..b5cc572
--- /dev/null
+++ b/library/RLCMAC_CSN1_Types.ttcn
@@ -0,0 +1,503 @@
+/* GPRS RLC/MAC Control Messages as per 3GPP TS 44.060 manually transcribed from the CSN.1 syntax, as no CSN.1
+ * tool for Eclipse TITAN could be found.  Implements only the minimum necessary messages for Osmocom teseting
+ * purposes.
+ * (C) 2017 by Harald Welte <laforge@gnumonks.org> */
+module RLCMAC_CSN1_Types {
+	import from General_Types all;
+	import from Osmocom_Types all;
+	import from GSM_Types all;
+
+	/* TS 44.060 11.2.0.1 */
+	type enumerated RlcmacDlCtrlMsgType {
+		PACKET_ACCESS_REJECT		('100001'B),
+		PACKET_CELL_CHANGE_ORDER	('000001'B),
+		PACKET_DL_ASSIGNMENT		('000010'B),
+		PACKET_MEASUREMENT_ORDER	('000011'B),
+		PACKET_PAGING_REQUEST		('100010'B),
+		PACKET_PDCH_RELEASE		('100011'B),
+		PACKET_POLLING_REQUEST		('000100'B),
+		/* TODO */
+		PACKET_TBF_RELEASE		('001000'B),
+		PACKET_UL_ACK_NACK		('001001'B),
+		PACKET_UL_ASSIGNMENT		('001010'B),
+		PACKET_DL_DUMMY_CTRL		('100101'B)
+	} with { variant "FIELDLENGTH(6)" };
+
+	/* TS 44.060 11.2.0.2 */
+	type enumerated RlcmacUlCtrlMsgType {
+		PACKET_CELL_CHANGE_FEATURE	('000000'B),
+		PACKET_CONTROL_ACK		('000001'B),
+		PACKET_DL_ACK_NACK		('000010'B),
+		PACKET_UL_DUMMY_CTRL		('000011'B),
+		PACKET_MEASUREMENT_REPORT	('000100'B),
+		PACKET_ENH_MEASUREMENT_REPORT	('001010'B),
+		PACKET_RESOURCE_REQUEST		('000101'B),
+		PACKET_MOBILE_TBF_STATUS	('000110'B),
+		PACKET_PSI_STATUS		('000111'B),
+		PACKET_EGPRS_DL_ACK_NACK	('001000'B),
+		PACKET_PAUSE			('001001'B),
+		ADDITIONAL_MS_RA_CAPABILITIES	('001011'B),
+		PACKET_CELL_CANGE_NOTIFICATION	('001100'B),
+		PACKET_SI_STATUS		('001101'B),
+		PACKET_CS_REQUEST		('001110'B),
+		MBMS_SERVICE_REQUEST		('001111'B),
+		MBMS_DL_ACK_NACK		('010000'B)
+	} with { variant "FIELDLENGTH(6)" };
+
+	type record NullGlobalTfi {
+		BIT1			presence ('0'B),
+		GlobalTfi		global_tfi
+	} with { variant "" };
+
+	type record TenTlli {
+		BIT2			presence ('10'B),
+		GprsTlli		tlli
+	} with { variant "" };
+
+	type union GlobalTfiOrTlli {
+		NullGlobalTfi		global_tfi,
+		TenTlli			tlli
+	};
+
+	/* 11.2.7 Packet Downlink Assignment */
+	type record PacketDlAssignment {
+		PageMode		page_mode,
+		BIT1			pres1,
+		PersistenceLevels	persistence_levels optional,
+		GlobalTfiOrTlli		tfi_or_tlli
+		/* TODO */
+	} with {
+		variant (persistence_levels) "PRESENCE(pres1 = '1'B)"
+	};
+
+	/* 11.2.29 Packet Uplink Assignment */
+	type record O_Gtfi {
+		BIT1			presence ('0'B),
+		GlobalTfi		global_tfi
+	} with { variant "" };
+	type record IO_Tlli {
+		BIT2			presence ('10'B),
+		GprsTlli		tlli
+	} with { variant "" };
+	type record IIO_Tqi {
+		BIT3			presence ('110'B),
+		PacketRequestReference	pkt_req_ref
+	} with { variant "" };
+	type union PktUlAssUnion {
+		O_Gtfi			global_tfi,
+		IO_Tlli			tlli,
+		IIO_Tqi			tqi
+	} with {
+		variant "TAG(global_tfi, presence = '0'B;
+			     tlli, presence = '10'B;
+			     tqi, presence = '110'B)"
+	};
+	type record DynamicAllocation {
+		BIT1			extd_dyn_alloc,
+		BIT1			p0_present,
+		uint4_t			p0 optional,
+		BIT1			pr_mode optional,
+		BIT1			usf_granularity,
+		BIT1			ul_tfi_ass_present,
+		uint5_t			ul_tfi_assignment optional,
+		BIT1			reserved ('0'B),
+		BIT1			tbf_starting_time_present,
+		StartingFnDesc		tbf_starting_time optional,
+		TsAllocationUnion	ts_allocation
+	} with {
+		variant (p0)		"PRESENCE(p0_present = '1'B)"
+		variant (pr_mode)	"PRESENCE(p0_present = '1'B)"
+		variant (ul_tfi_assignment) "PRESENCE(ul_tfi_ass_present = '1'B)"
+		variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
+	};
+	type record TsAllocationTs {
+		BIT1			presence,
+		uint3_t			usf_tn optional
+	} with {
+		variant (usf_tn) "PRESENCE(presence = '1'B)"
+	};
+	type record length(8) of TsAllocationTs TsAllocationTsArr;
+	type record TnGamma {
+		BIT1			presence,
+		uint3_t			usf_tn optional,
+		uint5_t			gamma_tn optional
+	} with {
+		variant (usf_tn)	"PRESENCE(presence = '1'B)"
+		variant (gamma_tn)	"PRESENCE(presence = '1'B)"
+	};
+	type record length(8) of TnGamma TnGamma8;
+	type record TsAllocationPwr {
+		uint4_t			alpha,
+		TnGamma			tn_gamma
+	} with { variant "" };
+	type record TsAllocationUnion {
+		BIT1			presence,
+		TsAllocationTsArr	ts optional,
+		TsAllocationPwr	ts_with_pwr optional
+	} with {
+		variant (ts)		"PRESENCE(presence = '0'B)"
+		variant (ts_with_pwr)	"PRESENCE(presence = '1'B)"
+	};
+	type record SingleBlockAllocation {
+		uint3_t			timeslot_nr,
+		BIT1			alpha_present,
+		uint4_t			alpha optional,
+		uint5_t			gamma_tn,
+		BIT1			p0_present,
+		uint4_t			p0 optional,
+		BIT1			reserved ('0'B) optional,
+		BIT1			pr_mode optional,
+		StartingFnDesc		tbf_starting_time
+	} with {
+		variant (alpha)		"PRESENCE(alpha_present = '1'B)"
+		variant (p0)		"PRESENCE(p0_present = '1'B)"
+		variant (reserved)	"PRESENCE(p0_present = '1'B)"
+		variant (pr_mode)	"PRESENCE(p0_present = '1'B)"
+	};
+	type record PktUlAssGprs {
+		ChCodingCommand		ch_coding_cmd,
+		BIT1			tlli_block_chan_coding,
+		PacketTimingAdvance	pkt_ta,
+		BIT1			freq_par_present,
+		FrequencyParameters	freq_par optional,
+		BIT2			alloc_present,
+		DynamicAllocation	dyn_block_alloc optional,
+		SingleBlockAllocation	sgl_block_alloc optional
+	} with {
+		variant (freq_par) "PRESENCE(freq_par_present = '1'B)"
+		variant (dyn_block_alloc) "PRESENCE(alloc_present = '01'B)"
+		variant (sgl_block_alloc) "PRESENCE(alloc_present = '10'B)"
+	};
+	type record PacketUlAssignment {
+		PageMode		page_mode,
+		BIT1			persistence_levels_present,
+		PersistenceLevels	persistence_levels optional,
+		PktUlAssUnion		identity,
+		BIT1			is_egprs,	/* msg escape */
+		PktUlAssGprs		gprs optional
+	} with {
+		variant (persistence_levels) "PRESENCE(persistence_levels_present = '1'B)"
+		variant (gprs) "PRESENCE(is_egprs = '0'B)"
+	};
+
+	/* 11.2.10 Packet Paging Request */
+	type record MobileIdentityLV {
+		uint4_t			len,
+		octetstring		mobile_id
+	} with { variant (len) "LENGTHTO(mobile_id)" };
+	type record PageInfoPs {
+		BIT1			presence ('0'B),
+		BIT1			ptmsi_or_mobile_id,
+		GsmTmsi			ptmsi optional,
+		MobileIdentityLV	mobile_identity optional
+	} with {
+		variant (ptmsi) "PRESENCE(ptmsi_or_mobile_id = '0'B)"
+		variant (mobile_identity) "PRESENCE(ptmsi_or_mobile_id = '1'B)"
+	};
+	type record PageInfoCs {
+		BIT1			presence ('1'B),
+		BIT1			tmsi_or_mobile_id,
+		GsmTmsi			tmsi optional,
+		MobileIdentityLV	mobile_identity optional,
+		ChannelNeeded		chan_needed,
+		BIT1			emlpp_prio_present,
+		uint3_t			emlpp_prio optional
+	} with {
+		variant (tmsi) "PRESENCE(tmsi_or_mobile_id = '0'B)"
+		variant (mobile_identity) "PRESENCE(tmsi_or_mobile_id = '1'B)"
+		variant (emlpp_prio) "PRESENCE(emlpp_prio_present = '1'B)"
+	};
+	type union PageInfo {
+		PageInfoPs		ps,
+		PageInfoCs		cs
+	};
+	type record PacketPagingReq {
+		PageMode		page_mode,
+		BIT1			persistence_levels_present,
+		PersistenceLevels	persistence_levels optional,
+		BIT1			nln_present,
+		uint2_t			nln optional
+		/* TODO: Repeated PageInfo */
+	} with {
+		variant (persistence_levels) "PRESENCE(persistence_levels_present = '1'B)"
+		variant (nln) "PRESENCE(nln_present = '1'B)"
+	};
+
+	/* 11.2.28 Uplink Ack/Nack */
+	type enumerated ChCodingCommand {
+		CH_CODING_CS1		('00'B),
+		CH_CODING_CS2		('01'B),
+		CH_CODING_CS3		('10'B),
+		CH_CODING_CS4		('11'B)
+	} with { variant "FIELDLENGTH(2)" };
+	type record UlAckNackGprs {
+		ChCodingCommand		ch_coding_cmd,
+		AckNackDescription	ack_nack_desc,
+		BIT1			cont_res_tlli_present,
+		GprsTlli		cont_res_tlli optional,
+		BIT1			pkt_ta_present,
+		PacketTimingAdvance	pkt_ta optional,
+		BIT1			pwr_ctrl_present,
+		PowerControlParameters	pwr_ctrl optional
+		/* TODO: Extension Bits, Rel5 ,... */
+	} with {
+		variant (cont_res_tlli)	"PRESENCE(cont_res_tlli_present = '1'B)"
+		variant (pkt_ta)	"PRESENCE(pkt_ta_present = '1'B)"
+		variant (pwr_ctrl)	"PRESENCE(pwr_ctrl_present = '1'B)"
+	};
+	type record PacketUlAckNack {
+		PageMode		page_mode,
+		BIT2			msg_excape ('00'B),
+		uint5_t			uplink_tfi,
+		BIT1			is_egprs ('0'B),	/* msg escape */
+		UlAckNackGprs		gprs optional
+		/* TODO: EGPRS */
+	} with { variant (gprs) "PRESENCE(is_egprs = '0'B)" };
+
+	/* 11.2.8 Packet Downlink Dummy Control Block */
+	type record PacketDlDummy {
+		PageMode		page_mode,
+		BIT1			persistence_levels_present,
+		PersistenceLevels	persistence_levels optional
+	} with {
+		variant (persistence_levels) "PRESENCE(persistence_levels_present = '1'B)"
+	};
+
+	/* 11.2.0.1 */
+	type union RlcmacDlCtrlUnion {
+		PacketDlAssignment	dl_assignment,
+		PacketUlAssignment	ul_assignment,
+		PacketPagingReq		paging,
+		PacketUlAckNack		ul_ack_nack,
+		PacketDlDummy		dl_dummy
+	} with { variant "" };
+
+	type record RlcmacDlCtrlMsg {
+		RlcmacDlCtrlMsgType	msg_type,
+		RlcmacDlCtrlUnion	u
+	} with {
+		variant (u) "CROSSTAG(dl_assignment,	msg_type = PACKET_DL_ASSIGNMENT;
+				      ul_assignment,	msg_type = PACKET_UL_ASSIGNMENT;
+				      paging,		msg_type = PACKET_PAGING_REQUEST;
+				      ul_ack_nack,	msg_type = PACKET_UL_ACK_NACK;
+				      dl_dummy,		msg_type = PACKET_DL_DUMMY_CTRL
+			)"
+	};
+
+	external function enc_RlcmacDlCtrlMsg(in RlcmacDlCtrlMsg si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_RlcmacDlCtrlMsg(in octetstring stream) return RlcmacDlCtrlMsg
+		with { extension "prototype(convert) decode(RAW)" };
+
+
+	/* 11.2.6 Packet Downlikn Ack/Nack */
+	type record ILevel {
+		BIT1	presence,
+		uint4_t	i_level optional
+	} with { variant (i_level) "PRESENCE(presence = '1'B)" };
+	type record length(8) of ILevel ILevels;
+	type record ChannelQualityReport {
+		uint6_t			c_value,
+		uint3_t			rxqual,
+		uint6_t			sign_var,
+		ILevels			i_levels
+	} with { variant "" };
+	type record PacketDlAckNack {
+		uint5_t			dl_tfi,
+		AckNackDescription	ack_nack_desc,
+		BIT1			chreq_desc_presence,
+		ChannelReqDescription	chreq_desc optional,
+		ChannelQualityReport	ch_qual_rep
+	} with { variant "" };
+
+	/* 11.2.2 Packet Control Acknowledgement */
+	type enumerated CtrlAck {
+		MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN_NEW_TFI	('00'B),
+		MS_RCVD_RBSN1_NO_RBSN0				('01'B),
+		MS_RCVD_RBSN0_NO_RBSN1				('10'B),
+		MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN		('11'B)
+	} with { variant "FIELDLENGTH(2)" };
+	type record PacketCtrlAck {
+		GprsTlli		tlli,
+		CtrlAck			ctrl_ack
+		/* TODO: Rel5 additions */
+	} with { variant "" };
+
+	/* 1.2.8b Packet Uplink Dummy Control Block */
+	type record PacketUlDummy {
+		GprsTlli		tlli
+	} with { variant "" };
+
+	/* 11.2.0.2 */
+	type union RlcmacUlCtrlUnion {
+		PacketCtrlAck		ctrl_ack,
+		PacketDlAckNack		dl_ack_nack,
+		PacketUlDummy		ul_dummy
+	} with { variant "" };
+
+	type record RlcmacUlCtrlMsg {
+		RlcmacUlCtrlMsgType	msg_type,
+		RlcmacUlCtrlUnion	u
+	} with {
+		variant (u) "CROSSTAG(ctrl_ack,		msg_type = PACKET_CONTROL_ACK;
+				      dl_ack_nack,	msg_type = PACKET_DL_ACK_NACK;
+				      ul_dummy,		msg_type = PACKET_UL_DUMMY_CTRL
+			)"
+	};
+
+	external function enc_RlcmacUlCtrlMsg(in RlcmacUlCtrlMsg si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_RlcmacUlCtrlMsg(in octetstring stream) return RlcmacUlCtrlMsg
+		with { extension "prototype(convert) decode(RAW)" };
+
+	type bitstring ReceivedBlockBitmap length(64) with { variant "BYTEORDER(last)" };
+
+	/* 12.3 Ack/Nack Description */
+	type record AckNackDescription {
+		BIT1			final_ack,
+		uint7_t			starting_seq_nr,
+		ReceivedBlockBitmap	receive_block_bitmap
+	} with { variant "" };
+
+	/* 12.7 Channel Request Description */
+	type enumerated RlcMode {
+		RLC_MODE_ACKNOWLEDGED	(0),
+		RLC_MODE_UNACKNOWLEDGED	(1)
+	} with { variant "FIELDLENGTH(1)" };
+	type enumerated LlcPduType {
+		LLC_PDU_IS_SACK_OR_ACK	(0),
+		LLC_PDU_IS_NOT_SACK_OR_ACK (1)
+	} with { variant "FIELDLENGTH(1)" };
+	type record ChannelReqDescription {
+		uint4_t			peak_tput_class,
+		uint2_t			priority,
+		RlcMode			rlc_mode,
+		LlcPduType		llc_pdu_type,
+		uint16_t		RlcOctetCount
+	} with { variant "" };
+
+	/* 12.8 Frequency Parameters */
+	type record FreqIndirect {
+		uint6_t			maio,
+		uint4_t			ma_number,
+		BIT1			change_mark1_present,
+		uint2_t			change_mark1 optional,
+		BIT1			change_mark2_present,
+		uint2_t			change_mark2 optional
+	} with {
+		variant (change_mark1) "PRESENCE(change_mark1_present = '1'B)"
+		variant (change_mark2) "PRESENCE(change_mark2_present = '1'B)"
+	};
+	type record FreqDirect1 {
+		uint6_t			maio,
+		GprsMobileAllication	mobile_allocation
+	}
+	type record FreqDirect2 {
+		uint6_t			maio,
+		uint6_t			hsn,
+		uint4_t			ma_freq_len,
+		octetstring		m1_freq_list
+	} with {
+		/* FIXME: this can not be expressed in TTCN-3 ?!? */
+		//variant (ma_freq_len) "LENGTHTO(m1_freq_list)+3"
+		variant (ma_freq_len) "LENGTHTO(m1_freq_list)"
+	};
+	type record FrequencyParameters {
+		uint3_t			tsc,
+		BIT2			presence,
+		uint10_t		arfcn optional,
+		FreqIndirect		indirect optional,
+		FreqDirect1		direct1 optional,
+		FreqDirect2		direct2 optional
+	} with {
+		variant (arfcn) "PRESENCE(presence = '00'B)"
+		variant (indirect) "PRESENCE(presence = '01'B)"
+		variant (direct1) "PRESENCE(presence = '10'B)"
+		variant (direct2) "PRESENCE(presence = '11'B)"
+	};
+
+	/* 12.10 Global TFI */
+	type record GlobalTfi {
+		boolean			is_dl_tfi,
+		uint5_t			tfi
+	} with { variant (is_dl_tfi) "FIELDLENGTH(1)" };
+
+	/* 12.10a GPRS Mobile Allocation */
+	type record RflNumberList {
+		uint4_t			rfl_number,
+		BIT1			presence,
+		RflNumberList		rfl_number_list optional
+	} with {
+		variant (rfl_number_list) "PRESENCE(presence = '1'B)"
+	};
+	type record GprsMobileAllication {
+		uint6_t			hsn,
+		BIT1			rfl_number_list_present,
+		RflNumberList		rfl_number_list optional,
+		BIT1			ma_present,
+		uint6_t			ma_length optional,
+		bitstring		ma_bitmap optional
+		/* TODO: ARFCN index list */
+	} with {
+		variant (rfl_number_list) "PRESENCE(rfl_number_list_present = '1'B)"
+		variant (ma_length) "PRESENCE(ma_present = '0'B)"
+		variant (ma_bitmap) "PRESENCE(ma_present = '0'B)"
+		/* FIXME: this can not be expressed in TTCN-3 ?!? */
+		//variant (ma_length) "LENGTHTO(ma_bitmap)+1"
+		variant (ma_length) "LENGTHTO(ma_bitmap)"
+	}
+
+	/* 12.11 Packet Request Reference */
+	type record PacketRequestReference {
+		uint11_t		ra_info,
+		uint16_t		frame_nr
+	} with { variant "" };
+
+	/* 12.12 Packet Timing Advance */
+	type record PacketTimingAdvance {
+		BIT1		val_present,
+		uint6_t		val optional,
+		BIT1		idx_present,
+		uint4_t		idx optional,
+		uint3_t		timeslot_nr optional
+	} with {
+		variant (val) "PRESENCE(val_present = '1'B)"
+		variant (idx) "PRESENCE(idx_present = '1'B)"
+		variant (timeslot_nr) "PRESENCE(idx_present = '1'B)"
+	};
+
+	/* 12.13 Power Control Parameters */
+	type record ZeroOneGamma {
+		BIT1		gamma_present,
+		uint5_t		gamma
+	} with {
+		variant (gamma) "PRESENCE (gamma_present = '1'B)"
+	};
+	type record length(8) of ZeroOneGamma ZeroOneGammas;
+	type record PowerControlParameters {
+		uint4_t		alpha,
+		ZeroOneGammas	gamma
+	} with { variant "" };
+
+	/* 12.14 Persistence Level */
+	type record length(4) of uint4_t PersistenceLevels;
+
+	/* 12.20 Page Mode */
+	type enumerated PageMode {
+		PAGE_MODE_NORMAL	('00'B),
+		PAGE_MODE_EXTENDED	('01'B),
+		PAGE_MODE_REORG		('10'B),
+		PAGE_MODE_SAME		('11'B)
+	} with { variant "FIELDLENGTH(2)" };
+
+	/* 12.21 Starting Frame Number */
+	type record StartingFnDesc {
+		BIT1		presence,
+		uint16_t	absolute_starting_time optional,
+		uint13_t	relative_k optional
+	} with {
+		variant (absolute_starting_time) "PRESENCE(presence = '0'B)"
+		variant (relative_k) "PRESENCE(presence = '1'B)"
+	};
+
+} with { encode "RAW"; variant "FIELDORDER(msb)" variant "BYTEORDER(last)" };
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)" }