blob: 38147f39fd07b9f2d8457502d2655b7aea83e305 [file] [log] [blame]
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +02001/* TITAN REW encode/decode definitions for 3GPP TS 44.060 RLC/MAC Blocks */
2
3/* (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
4 * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13module RLCMAC_Templates {
14 import from General_Types all;
15 import from Osmocom_Types all;
16 import from GSM_Types all;
17 import from RLCMAC_CSN1_Types all;
18 import from RLCMAC_CSN1_Templates all;
19 import from RLCMAC_Types all;
20
21 /* TS 44.060 10.4.5 */
22 function f_rrbp_fn_delay(MacRrbp rrbp) return uint32_t {
23 select (rrbp) {
24 case (RRBP_Nplus13_mod_2715648) { return 13; }
25 case (RRBP_Nplus17_or_18_mod_2715648) { return 17; }
26 case (RRBP_Nplus21_or_22_mod_2715648) { return 21; }
27 case (RRBP_Nplus26_mod_2715648) { return 26; }
28 }
29 return 0;
30 }
31
Pau Espin Pedrol27d6af52020-04-30 20:13:32 +020032 function f_rlcmac_mcs2headertype(CodingScheme mcs) return EgprsHeaderType {
33 select (mcs) {
34 case (MCS_0) { return RLCMAC_HDR_TYPE_3; }
35 case (MCS_1) { return RLCMAC_HDR_TYPE_3; }
36 case (MCS_2) { return RLCMAC_HDR_TYPE_3; }
37 case (MCS_3) { return RLCMAC_HDR_TYPE_3; }
38 case (MCS_4) { return RLCMAC_HDR_TYPE_3; }
39 case (MCS_5) { return RLCMAC_HDR_TYPE_2; }
40 case (MCS_6) { return RLCMAC_HDR_TYPE_2; }
41 case (MCS_7) { return RLCMAC_HDR_TYPE_1; }
42 case (MCS_8) { return RLCMAC_HDR_TYPE_1; }
43 case (MCS_9) { return RLCMAC_HDR_TYPE_1; }
44 }
45 return RLCMAC_HDR_TYPE_3;
46 }
47
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +020048 function f_rlcmac_cs_mcs2block_len(CodingScheme cs_mcs) return uint32_t {
49 select (cs_mcs) {
50 case (CS_1) { return 23; }
51 case (CS_2) { return 34; }
52 case (CS_3) { return 40; }
53 case (CS_4) { return 54; }
54 case (MCS_1) { return 27; }
55 case (MCS_2) { return 33; }
56 case (MCS_3) { return 42; }
57 case (MCS_4) { return 49; }
58 case (MCS_5) { return 61; }
59 case (MCS_6) { return 79; }
60 case (MCS_7) { return 119; }
61 case (MCS_8) { return 143; }
62 case (MCS_9) { return 155; }
63 }
64 return 0;
65 }
66
67 function f_rlcmac_block_len2cs_mcs(uint32_t len) return CodingScheme {
68 select (len) {
69 case (23) { return CS_1; }
70 case (34) { return CS_2; }
71 case (40) { return CS_3; }
72 case (54) { return CS_4; }
73 case (27) { return MCS_1; }
74 case (33) { return MCS_2; }
75 case (42) { return MCS_3; }
76 case (49) { return MCS_4; }
77 case (60) { return MCS_5; }
78 case (61) { return MCS_5; }
79 case (78) { return MCS_6; }
80 case (79) { return MCS_6; }
81 case (118) { return MCS_7; }
82 case (119) { return MCS_7; }
83 case (142) { return MCS_8; }
84 case (143) { return MCS_8; }
85 case (154) { return MCS_9; }
86 case (155) { return MCS_9; }
87 }
88 return CS_1;
89 }
90
Pau Espin Pedrol27d6af52020-04-30 20:13:32 +020091 /* Coding and Puncturing Scheme indicator field for Header type 1 in EGPRS TBF or EC TBF or downlink EGPRS2 TBF */
92 function f_rlcmac_cps_htype1_to_mcs(uint3_t cps) return CodingScheme {
93 var CodingSchemeArray egprs_Header_type1_coding_puncturing_scheme_to_mcs := {
94 MCS_9 /* 0x00, "(MCS-9/P1 ; MCS-9/P1)" */,
95 MCS_9 /* 0x01, "(MCS-9/P1 ; MCS-9/P2)" */,
96 MCS_9 /* 0x02, "(MCS-9/P1 ; MCS-9/P3)" */,
97 MCS_0 /* 0x03, "reserved" */,
98 MCS_9 /* 0x04, "(MCS-9/P2 ; MCS-9/P1)" */,
99 MCS_9 /* 0x05, "(MCS-9/P2 ; MCS-9/P2)" */,
100 MCS_9 /* 0x06, "(MCS-9/P2 ; MCS-9/P3)" */,
101 MCS_0 /* 0x07, "reserved" */,
102 MCS_9 /* 0x08, "(MCS-9/P3 ; MCS-9/P1)" */,
103 MCS_9 /* 0x09, "(MCS-9/P3 ; MCS-9/P2)" */,
104 MCS_9 /* 0x0A, "(MCS-9/P3 ; MCS-9/P3)" */,
105 MCS_8 /* 0x0B, "(MCS-8/P1 ; MCS-8/P1)" */,
106 MCS_8 /* 0x0C, "(MCS-8/P1 ; MCS-8/P2)" */,
107 MCS_8 /* 0x0D, "(MCS-8/P1 ; MCS-8/P3)" */,
108 MCS_8 /* 0x0E, "(MCS-8/P2 ; MCS-8/P1)" */,
109 MCS_8 /* 0x0F, "(MCS-8/P2 ; MCS-8/P2)" */,
110 MCS_8 /* 0x10, "(MCS-8/P2 ; MCS-8/P3)" */,
111 MCS_8 /* 0x11, "(MCS-8/P3 ; MCS-8/P1)" */,
112 MCS_8 /* 0x12, "(MCS-8/P3 ; MCS-8/P2)" */,
113 MCS_8 /* 0x13, "(MCS-8/P3 ; MCS-8/P3)" */,
114 MCS_7 /* 0x14, "(MCS-7/P1 ; MCS-7/P1)" */,
115 MCS_7 /* 0x15, "(MCS-7/P1 ; MCS-7/P2)" */,
116 MCS_7 /* 0x16, "(MCS-7/P1 ; MCS-7/P3)" */,
117 MCS_7 /* 0x17, "(MCS-7/P2 ; MCS-7/P1)" */,
118 MCS_7 /* 0x18, "(MCS-7/P2 ; MCS-7/P2)" */,
119 MCS_7 /* 0x19, "(MCS-7/P2 ; MCS-7/P3)" */,
120 MCS_7 /* 0x1A, "(MCS-7/P3 ; MCS-7/P1)" */,
121 MCS_7 /* 0x1B, "(MCS-7/P3 ; MCS-7/P2)" */,
122 MCS_7 /* 0x1C, "(MCS-7/P3 ; MCS-7/P3)" */,
123 MCS_0 /* 0x1D, "reserved" */,
124 MCS_0 /* 0x1E, "reserved" */,
125 MCS_0 /* 0x1F, "reserved" */
126 };
127 return egprs_Header_type1_coding_puncturing_scheme_to_mcs[cps];
128 }
129
130 /* Coding and Puncturing Scheme indicator field for Header type 2 in (EC-)EGPRS TBF or uplink EGPRS2-A TBF */
131 function f_rlcmac_cps_htype2_to_mcs(uint3_t cps) return CodingScheme {
132 var CodingSchemeArray egprs_Header_type2_coding_puncturing_scheme_to_mcs := {
133 MCS_6 /* {0x00, "MCS-6/P1"} */,
134 MCS_6 /* {0x01, "MCS-6/P2"} */,
135 MCS_6 /* {0x02, "MCS-6/P1 with 6 octet padding"} */,
136 MCS_6 /* {0x03, "MCS-6/P2 with 6 octet padding "} */,
137 MCS_5 /* {0x04, "MCS-5/P1"} */,
138 MCS_5 /* {0x05, "MCS-5/P2"} */,
139 MCS_5 /* {0x06, "MCS-6/P1 with 10 octet padding "} */,
140 MCS_5 /* {0x07, "MCS-6/P2 with 10 octet padding "} */
141 };
142 return egprs_Header_type2_coding_puncturing_scheme_to_mcs[cps];
143 }
144
145 /* Coding and Puncturing Scheme indicator field for Header type 3 */
146 function f_rlcmac_cps_htype3_to_mcs(uint3_t cps) return CodingScheme {
147 var CodingSchemeArray egprs_Header_type3_coding_puncturing_scheme_to_mcs := {
148 MCS_4 /* {0x00, "MCS-4/P1"} */,
149 MCS_4 /* {0x01, "MCS-4/P2"} */,
150 MCS_4 /* {0x02, "MCS-4/P3"} */,
151 MCS_3 /* {0x03, "MCS-3/P1"} */,
152 MCS_3 /* {0x04, "MCS-3/P2"} */,
153 MCS_3 /* {0x05, "MCS-3/P3"} */,
154 MCS_3 /* {0x06, "MCS-3/P1 with padding"} */,
155 MCS_3 /* {0x07, "MCS-3/P2 with padding"} */,
156 MCS_3 /* {0x08, "MCS-3/P3 with padding"} */,
157 MCS_2 /* {0x09, "MCS-2/P1"} */,
158 MCS_2 /* {0x0A, "MCS-2/P2"} */,
159 MCS_1 /* {0x0B, "MCS-1/P1"} */,
160 MCS_1 /* {0x0C, "MCS-1/P2"} */,
161 MCS_2 /* {0x0D, "MCS-2/P1 with padding"} */,
162 MCS_2 /* {0x0E, "MCS-2/P2 with padding"} */,
163 MCS_0 /* {0x0F, "MCS-0"} */
164 };
165 return egprs_Header_type3_coding_puncturing_scheme_to_mcs[cps];
166 }
167
168 function f_rlcmac_cps_htype_to_mcs(uint3_t cps, EgprsHeaderType htype) return CodingScheme {
169 select (htype) {
170 case (RLCMAC_HDR_TYPE_1) { return f_rlcmac_cps_htype1_to_mcs(cps); }
171 case (RLCMAC_HDR_TYPE_2) { return f_rlcmac_cps_htype2_to_mcs(cps); }
172 case (RLCMAC_HDR_TYPE_3) { return f_rlcmac_cps_htype3_to_mcs(cps); }
173 }
174 //TODO: return error here.
175 return CS_1;
176 }
177
178 function f_rlcmac_mcs_to_cps_htype1(CodingScheme mcs, uint2_t part, boolean with_padding) return uint5_t {
179 //TODO: implement similar to f_rlcmac_mcs_to_cps_htype3()
180 //TODO: return error here.
181 return 0;
182 }
183
184 function f_rlcmac_mcs_to_cps_htype2(CodingScheme mcs, uint2_t part, boolean with_padding) return uint5_t {
185 //TODO: implement similar to f_rlcmac_mcs_to_cps_htype3()
186 //TODO: return error here.
187 return 0;
188 }
189
190 function f_rlcmac_mcs_to_cps_htype3(CodingScheme mcs, uint2_t part, boolean with_padding) return uint5_t {
191 select (mcs) {
192 case (MCS_4) {
193 select (part) {
194 case (1) { return 0; /* {0x00, "MCS-4/P1"} */ }
195 case (2) { return 1; /* {0x01, "MCS-4/P2"} */ }
196 case (3) { return 2; /* {0x01, "MCS-4/P2"} */ }
197 }
198 }
199 case (MCS_3) {
200 if (not with_padding) {
201 select (part) {
202 case (1) { return 3; /* {0x03, "MCS-3/P1"} */ }
203 case (2) { return 4; /* {0x04, "MCS-3/P2"} */ }
204 case (3) { return 5; /* {0x05, "MCS-3/P3"} */ }
205 }
206 } else {
207 select (part) {
208 case (1) { return 6; /* {0x06, "MCS-3/P1 with padding"} */ }
209 case (2) { return 7; /* {0x07, "MCS-3/P2 with padding"} */ }
210 case (3) { return 8; /* {0x08, "MCS-3/P3 with padding"} */ }
211 }
212 }
213 }
214 case (MCS_2) {
215 if (not with_padding) {
216 select (part) {
217 case (1) { return 9; /* {0x09, "MCS-2/P1"} */ }
218 case (2) { return 10; /* {0x0A, "MCS-2/P2"} */ }
219 }
220 } else {
221 select (part) {
222 case (1) { return 13; /* {0x0D, "MCS-2/P1 with padding"} */ }
223 case (2) { return 14; /* {0x0E, "MCS-2/P2 with padding"} */}
224 }
225 }
226 }
227 case (MCS_1) {
228 select (part) {
229 case (1) { return 11; /* {0x0B, "MCS-1/P1"} */ }
230 case (2) { return 12; /* {0x0C, "MCS-1/P2"} */ }
231 }
232 }
233 case (MCS_0) { return 15; /* {0x0F, "MCS-0"} */ }
234 }
235 //TODO: return error here.
236 return 0;
237 }
238
239 function f_rlcmac_mcs_to_cps(CodingScheme mcs, uint2_t part, boolean with_padding := false) return uint5_t {
240
241 var EgprsHeaderType htype := f_rlcmac_mcs2headertype(mcs);
242 select (htype) {
243 case (RLCMAC_HDR_TYPE_1) { return f_rlcmac_mcs_to_cps_htype1(mcs, part, with_padding); }
244 case (RLCMAC_HDR_TYPE_2) { return f_rlcmac_mcs_to_cps_htype2(mcs, part, with_padding); }
245 case (RLCMAC_HDR_TYPE_3) { return f_rlcmac_mcs_to_cps_htype3(mcs, part, with_padding); }
246 }
247 //TODO: return error here.
248 return 0;
249 }
250
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +0200251 template (value) RlcmacUlBlock ts_RLC_UL_CTRL_ACK(RlcmacUlCtrlMsg ctrl,
252 MacPayloadType pt := MAC_PT_RLCMAC_NO_OPT,
253 boolean retry := false) := {
254 ctrl := {
255 mac_hdr := {
256 payload_type := pt,
257 spare := '00000'B,
258 retry := retry
259 },
260 payload := ctrl
261 }
262 }
263
264 /* Send Template for Downlink ACK/NACK */
265 template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK(template uint5_t tfi, AckNackDescription andesc, boolean retry := false) := {
266 ctrl := {
267 mac_hdr := {
268 payload_type := MAC_PT_RLCMAC_NO_OPT,
269 spare := '00000'B,
270 retry := retry
271 },
272 payload := {
273 msg_type := PACKET_DL_ACK_NACK,
274 u := {
275 dl_ack_nack := {
276 dl_tfi := tfi,
277 ack_nack_desc := andesc,
278 chreq_desc_presence := '0'B,
279 chreq_desc := omit,
280 ch_qual_rep := c_ChQualRep_default
281 }
282 }
283 }
284 }
285 }
286
287 /* Template for uplink Data block */
288 template RlcmacUlBlock t_RLCMAC_UL_DATA(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
289 template LlcBlocks blocks := {}, template boolean stall := false) := {
290 data := {
291 mac_hdr := {
292 payload_type := MAC_PT_RLC_DATA,
293 countdown := cv,
294 stall_ind := false,
295 retry := false,
296 spare := '0'B,
297 pfi_ind := false,
298 tfi := tfi,
299 tlli_ind := false,
300 bsn := bsn,
301 e := false
302 },
303 tlli := omit,
304 pfi := omit,
305 blocks := blocks
306 }
307 }
308 template RlcmacUlBlock t_RLCMAC_UL_DATA_TLLI(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
309 template LlcBlocks blocks := {}, template boolean stall := false, template GprsTlli tlli) := {
310 data := {
311 mac_hdr := {
312 payload_type := MAC_PT_RLC_DATA,
313 countdown := cv,
314 stall_ind := false,
315 retry := false,
316 spare := '0'B,
317 pfi_ind := false,
318 tfi := tfi,
319 tlli_ind := true,
320 bsn := bsn,
321 e := false
322 },
323 tlli := tlli,
324 pfi := omit,
325 blocks := blocks
326 }
327 }
328
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200329 /* Template for uplink Data block */
330 template RlcmacUlBlock t_RLCMAC_UL_EGPRS_DATA(CodingScheme mcs,
331 template uint5_t tfi, template uint4_t cv,
332 template uint11_t bsn1, template EgprsLlcBlocks blocks := {}) := {
333 data_egprs := {
334 mac_hdr := {
335 header_type := f_rlcmac_mcs2headertype(mcs),
336 tfi := tfi,
337 countdown := cv,
338 foi_si := '0'B,
339 r_ri := '0'B,
340 bsn1 := bsn1,
341 cps := f_rlcmac_mcs_to_cps(mcs, 1, false),
342 pfi_ind := false,
343 rsb := '0'B,
344 spb := '00'B
345 },
346 tlli_ind := false,
347 e := false,
348 tlli := omit,
349 pfi := omit,
350 blocks := blocks
351 }
352 }
353
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +0200354 template DlMacHeader t_RLCMAC_DlMacH(template MacPayloadType pt, template MacRrbp rrbp, template
355uint3_t usf) := {
356 payload_type := pt,
357 rrbp := rrbp,
358 rrbp_valid := ispresent(rrbp),
359 usf := usf
360 }
361
362 template RlcmacDlBlock tr_RLCMAC_DUMMY_CTRL(template uint3_t usf := ?, template PageMode page_mode := ?) := {
363 ctrl := {
364 mac_hdr := {
365 payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
366 rrbp:= ?,
367 rrbp_valid := ?,
368 usf := usf
369 },
370 opt := *,
371 payload := {
372 msg_type := PACKET_DL_DUMMY_CTRL,
373 u := {
374 dl_dummy := {
375 page_mode := page_mode,
376 persistence_levels_present := ?,
377 persistence_levels := *
378 }
379 }
380 }
381 }
382 }
383
384 template RlcmacDlBlock tr_RLCMAC_DL_PACKET_ASS(template uint3_t usf := ?) := {
385 ctrl := {
386 mac_hdr := {
387 payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
388 rrbp:= ?,
389 rrbp_valid := ?,
390 usf := usf
391 },
392 opt := *,
393 payload := {
394 msg_type := PACKET_DL_ASSIGNMENT,
395 u := {
396 dl_assignment := {
397 page_mode := ?,
398 pres1 := ?,
399 persistence_levels := *,
400 tfi_or_tlli := ?
401 }
402 }
403 }
404 }
405 }
406
407 template RlcmacDlBlock tr_RLCMAC_UL_PACKET_ASS(template uint3_t usf := ?) := {
408 ctrl := {
409 mac_hdr := {
410 payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
411 rrbp:= ?,
412 rrbp_valid := ?,
413 usf := usf
414 },
415 opt := *,
416 payload := {
417 msg_type := PACKET_UL_ASSIGNMENT,
418 u := {
419 ul_assignment := {
420 page_mode := ?,
421 persistence_levels_present := ?,
422 persistence_levels := *,
423 identity := ?,
424 is_egprs := ?, /* msg escape */
425 gprs := *
426 }
427 }
428 }
429 }
430 }
431
432
433 /* Receive Template for Uplink ACK/NACK */
434 template RlcmacDlBlock tr_RLCMAC_UL_ACK_NACK(template uint5_t ul_tfi, template GprsTlli tlli := ?) := {
435 ctrl := {
436 mac_hdr := {
437 payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
438 rrbp:= ?,
439 rrbp_valid := ?,
440 usf := ?
441 },
442 opt := *,
443 payload := {
444 msg_type := PACKET_UL_ACK_NACK,
445 u := {
446 ul_ack_nack := {
447 page_mode := ?,
448 msg_excape := ?,
449 uplink_tfi := ul_tfi,
450 is_egprs := '0'B,
451 gprs := {
452 ch_coding_cmd := ?,
453 ack_nack_desc := ?,
454 cont_res_tlli_present := ?,
455 cont_res_tlli := tlli,
456 pkt_ta_present := ?,
457 pkt_ta := *,
458 pwr_ctrl_present := ?,
459 pwr_ctrl := *
460 }
461 }
462 }
463 }
464 }
465 }
466
467 template RlcmacDlBlock tr_RLCMAC_PACKET_PAG_REQ(template uint3_t usf := ?) := {
468 ctrl := {
469 mac_hdr := {
470 payload_type := MAC_PT_RLCMAC_NO_OPT,
471 rrbp:= ?,
472 rrbp_valid := ?,
473 usf := usf
474 },
475 opt := *,
476 payload := {
477 msg_type := PACKET_PAGING_REQUEST,
478 u := {
479 paging := {
480 page_mode := ?,
481 persistence_levels_present := ?,
482 persistence_levels := *,
483 nln_present := ?,
484 nln := *,
485 repeated_pageinfo_present := ?,
486 repeated_pageinfo := *
487 }
488 }
489 }
490 }
491 }
492
493 template RlcmacDlBlock tr_RLCMAC_DATA_RRBP := {
494 data := {
495 mac_hdr := {
496 mac_hdr := {
497 payload_type := MAC_PT_RLC_DATA,
498 rrbp := ?,
499 rrbp_valid := true,
500 usf := ?
501 },
502 hdr_ext := ?
503 },
504 blocks := ?
505 }
506 }
507
508 template RlcmacDlBlock tr_RLCMAC_DATA_EGPRS := {
509 data_egprs := {
510 mac_hdr := ?,
511 fbi := ?,
512 e := ?,
513 blocks := ?
514 }
515 }
516
517 /* Template for Uplink MAC Control Header */
518 template UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template MacPayloadType pt, template boolean retry := false) := {
519 payload_type := pt,
520 spare := '00000'B,
521 retry := retry
522 }
523
524 /* Template for Uplink Control ACK */
525 template RlcmacUlBlock ts_RLCMAC_CTRL_ACK(GprsTlli tlli, CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
526 ctrl := {
527 mac_hdr := t_RLCMAC_UlMacCtrlH(MAC_PT_RLCMAC_NO_OPT),
528 payload := {
529 msg_type := PACKET_CONTROL_ACK,
530 u := {
531 ctrl_ack := {
532 tlli := tlli,
533 ctrl_ack := ack
534 }
535 }
536 }
537 }
538 }
539
540 /* Template for a LlcBlock (part of a LLC frame inside RlcMac?lDataBlock */
541 template LlcBlock t_RLCMAC_LLCBLOCK(octetstring data, boolean more := false, boolean e := true) := {
542 /* let encoder figure out the header */
543 hdr := omit,
544 payload := data
545 }
546
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200547 /* Template for a LlcBlock (part of a LLC frame inside RlcMacEgprs?lDataBlock */
548 template EgprsLlcBlock t_RLCMAC_LLCBLOCK_EGPRS(octetstring data, boolean e := true) := {
549 /* let encoder figure out the header */
550 hdr := omit,
551 payload := data
552 }
553
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +0200554} with { encode "RAW"; variant "FIELDORDER(msb)" }