Split templates in RLCMAC_{CSN1_}Types into their own _Templates file

RLCMAC blocks have a lot of fields and we will potentially require lots
of different templates, as well as functions to handle related structs.

Change-Id: I9c6597178168aa3848b21930f33be698dd2ce545
diff --git a/library/RLCMAC_Templates.ttcn b/library/RLCMAC_Templates.ttcn
new file mode 100644
index 0000000..8fb6b0c
--- /dev/null
+++ b/library/RLCMAC_Templates.ttcn
@@ -0,0 +1,346 @@
+/* TITAN REW encode/decode definitions for 3GPP TS 44.060 RLC/MAC Blocks */
+
+/* (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
+ * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module RLCMAC_Templates {
+	import from General_Types all;
+	import from Osmocom_Types all;
+	import from GSM_Types all;
+	import from RLCMAC_CSN1_Types all;
+	import from RLCMAC_CSN1_Templates all;
+	import from RLCMAC_Types all;
+
+	/* TS 44.060 10.4.5 */
+	function f_rrbp_fn_delay(MacRrbp rrbp) return uint32_t {
+		select (rrbp) {
+		case (RRBP_Nplus13_mod_2715648) { return 13; }
+		case (RRBP_Nplus17_or_18_mod_2715648) { return 17; }
+		case (RRBP_Nplus21_or_22_mod_2715648) { return 21;  }
+		case (RRBP_Nplus26_mod_2715648) { return 26; }
+		}
+		return 0;
+	}
+
+	function f_rlcmac_cs_mcs2block_len(CodingScheme cs_mcs) return uint32_t {
+		select (cs_mcs) {
+		case (CS_1) { return 23; }
+		case (CS_2) { return 34; }
+		case (CS_3) { return 40; }
+		case (CS_4) { return 54; }
+		case (MCS_1) { return 27; }
+		case (MCS_2) { return 33; }
+		case (MCS_3) { return 42; }
+		case (MCS_4) { return 49; }
+		case (MCS_5) { return 61; }
+		case (MCS_6) { return 79; }
+		case (MCS_7) { return 119; }
+		case (MCS_8) { return 143; }
+		case (MCS_9) { return 155; }
+		}
+		return 0;
+	}
+
+	function f_rlcmac_block_len2cs_mcs(uint32_t len) return CodingScheme {
+		select (len) {
+			case (23) { return CS_1; }
+			case (34) { return CS_2; }
+			case (40) { return CS_3; }
+			case (54) { return CS_4; }
+			case (27) { return MCS_1; }
+			case (33) { return MCS_2; }
+			case (42) { return MCS_3; }
+			case (49) { return MCS_4; }
+			case (60) { return MCS_5; }
+			case (61) { return MCS_5; }
+			case (78) { return MCS_6; }
+			case (79) { return MCS_6; }
+			case (118) { return MCS_7; }
+			case (119) { return MCS_7; }
+			case (142) { return MCS_8; }
+			case (143) { return MCS_8; }
+			case (154) { return MCS_9; }
+			case (155) { return MCS_9; }
+		}
+		return CS_1;
+	}
+
+	template (value) RlcmacUlBlock ts_RLC_UL_CTRL_ACK(RlcmacUlCtrlMsg ctrl,
+							MacPayloadType pt := MAC_PT_RLCMAC_NO_OPT,
+							boolean retry := false) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := pt,
+				spare := '00000'B,
+				retry := retry
+			},
+			payload := ctrl
+		}
+	}
+
+	/* Send Template for Downlink ACK/NACK */
+	template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK(template uint5_t tfi, AckNackDescription andesc, boolean retry := false) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := MAC_PT_RLCMAC_NO_OPT,
+				spare := '00000'B,
+				retry := retry
+			},
+			payload := {
+				msg_type := PACKET_DL_ACK_NACK,
+				u := {
+					dl_ack_nack := {
+						dl_tfi := tfi,
+						ack_nack_desc := andesc,
+						chreq_desc_presence := '0'B,
+						chreq_desc := omit,
+						ch_qual_rep := c_ChQualRep_default
+					}
+				}
+			}
+		}
+	}
+
+	/* Template for uplink Data block */
+	template RlcmacUlBlock t_RLCMAC_UL_DATA(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
+						template LlcBlocks blocks := {}, template boolean stall := false) := {
+		data := {
+			mac_hdr := {
+				payload_type := MAC_PT_RLC_DATA,
+				countdown := cv,
+				stall_ind := false,
+				retry := false,
+				spare := '0'B,
+				pfi_ind := false,
+				tfi := tfi,
+				tlli_ind := false,
+				bsn := bsn,
+				e := false
+			},
+			tlli := omit,
+			pfi := omit,
+			blocks := blocks
+		}
+	}
+	template RlcmacUlBlock t_RLCMAC_UL_DATA_TLLI(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
+						     template LlcBlocks blocks := {}, template boolean stall := false, template GprsTlli tlli) := {
+		data := {
+			mac_hdr := {
+				payload_type := MAC_PT_RLC_DATA,
+				countdown := cv,
+				stall_ind := false,
+				retry := false,
+				spare := '0'B,
+				pfi_ind := false,
+				tfi := tfi,
+				tlli_ind := true,
+				bsn := bsn,
+				e := false
+			},
+			tlli := tlli,
+			pfi := omit,
+			blocks := blocks
+		}
+	}
+
+	template DlMacHeader t_RLCMAC_DlMacH(template MacPayloadType pt, template MacRrbp rrbp, template
+uint3_t usf) := {
+		payload_type := pt,
+		rrbp := rrbp,
+		rrbp_valid := ispresent(rrbp),
+		usf := usf
+	}
+
+	template RlcmacDlBlock tr_RLCMAC_DUMMY_CTRL(template uint3_t usf := ?, template PageMode page_mode := ?) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
+				rrbp:= ?,
+				rrbp_valid := ?,
+				usf := usf
+			},
+			opt := *,
+			payload := {
+				msg_type := PACKET_DL_DUMMY_CTRL,
+				u := {
+					dl_dummy := {
+						page_mode := page_mode,
+						persistence_levels_present := ?,
+						persistence_levels := *
+					}
+				}
+			}
+		}
+	}
+
+	template RlcmacDlBlock tr_RLCMAC_DL_PACKET_ASS(template uint3_t usf := ?) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
+				rrbp:= ?,
+				rrbp_valid := ?,
+				usf := usf
+			},
+			opt := *,
+			payload := {
+				msg_type := PACKET_DL_ASSIGNMENT,
+				u := {
+					dl_assignment := {
+						page_mode := ?,
+						pres1 := ?,
+						persistence_levels := *,
+						tfi_or_tlli := ?
+					}
+				}
+			}
+		}
+	}
+
+	template RlcmacDlBlock tr_RLCMAC_UL_PACKET_ASS(template uint3_t usf := ?) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
+				rrbp:= ?,
+				rrbp_valid := ?,
+				usf := usf
+			},
+			opt := *,
+			payload := {
+				msg_type := PACKET_UL_ASSIGNMENT,
+				u := {
+					ul_assignment := {
+						page_mode := ?,
+						persistence_levels_present := ?,
+						persistence_levels := *,
+						identity := ?,
+						is_egprs := ?,  /* msg escape */
+						gprs := *
+					}
+				}
+			}
+		}
+	}
+
+
+	/* Receive Template for Uplink ACK/NACK */
+	template RlcmacDlBlock tr_RLCMAC_UL_ACK_NACK(template uint5_t ul_tfi, template GprsTlli tlli := ?) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
+				rrbp:= ?,
+				rrbp_valid := ?,
+				usf := ?
+			},
+			opt := *,
+			payload := {
+				msg_type := PACKET_UL_ACK_NACK,
+				u := {
+					ul_ack_nack := {
+						page_mode := ?,
+						msg_excape := ?,
+						uplink_tfi := ul_tfi,
+						is_egprs := '0'B,
+						gprs := {
+							ch_coding_cmd := ?,
+							ack_nack_desc := ?,
+							cont_res_tlli_present := ?,
+							cont_res_tlli := tlli,
+							pkt_ta_present := ?,
+							pkt_ta := *,
+							pwr_ctrl_present := ?,
+							pwr_ctrl := *
+						}
+					}
+				}
+			}
+		}
+	}
+
+	template RlcmacDlBlock tr_RLCMAC_PACKET_PAG_REQ(template uint3_t usf := ?) := {
+		ctrl := {
+			mac_hdr := {
+				payload_type := MAC_PT_RLCMAC_NO_OPT,
+				rrbp:= ?,
+				rrbp_valid := ?,
+				usf := usf
+			},
+			opt := *,
+			payload := {
+				msg_type := PACKET_PAGING_REQUEST,
+				u := {
+					paging := {
+						page_mode := ?,
+						persistence_levels_present := ?,
+						persistence_levels := *,
+						nln_present := ?,
+						nln := *,
+						repeated_pageinfo_present := ?,
+						repeated_pageinfo := *
+					}
+				}
+			}
+		}
+	}
+
+	template RlcmacDlBlock tr_RLCMAC_DATA_RRBP := {
+		data := {
+			mac_hdr := {
+				mac_hdr := {
+					payload_type := MAC_PT_RLC_DATA,
+					rrbp := ?,
+					rrbp_valid := true,
+					usf := ?
+				},
+				hdr_ext := ?
+			},
+			blocks := ?
+		}
+	}
+
+	template RlcmacDlBlock tr_RLCMAC_DATA_EGPRS := {
+		data_egprs := {
+			mac_hdr := ?,
+			fbi := ?,
+			e := ?,
+			blocks := ?
+		}
+	}
+
+	/* Template for Uplink MAC Control Header */
+	template UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template MacPayloadType pt, template boolean retry := false) := {
+		payload_type := pt,
+		spare := '00000'B,
+		retry := retry
+	}
+
+	/* Template for Uplink Control ACK */
+	template RlcmacUlBlock ts_RLCMAC_CTRL_ACK(GprsTlli tlli, CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
+		ctrl := {
+			mac_hdr := t_RLCMAC_UlMacCtrlH(MAC_PT_RLCMAC_NO_OPT),
+			payload := {
+				msg_type := PACKET_CONTROL_ACK,
+				u := {
+					ctrl_ack := {
+						tlli := tlli,
+						ctrl_ack := ack
+					}
+				}
+			}
+		}
+	}
+
+	/* Template for a LlcBlock (part of a LLC frame inside RlcMac?lDataBlock */
+	template LlcBlock t_RLCMAC_LLCBLOCK(octetstring data, boolean more := false, boolean e := true) := {
+		/* let encoder figure out the header */
+		hdr := omit,
+		payload := data
+	}
+
+} with { encode "RAW"; variant "FIELDORDER(msb)" }