Rewrite Packet Uplink IA Rest Octets for SBA

Use bitvec_set_*() directly without external write pointer tracking to
simplify the code. This is part of IA Rest Octets (3GPP TS 44.018
ยง10.5.2.16) which is the last part of the message so it should not
interfere with the rest of encoding functions.

The difference in the expected test output is due to proper handling of
TAI which should not be transmitted for SBA according to the Note in
Table 10.5.2.16.1 in 3GPP TS 44.018.

The change was manually tested against real mobile phone using options
'gprs mode gprs' in osmo-bsc.cfg and 'two-phase-access' in osmo-pcu.cfg
to make sure appropriate code path is actually triggered.

That's partially based on reverted commit 93d947f5e8a30acc9250c124bf9d5bb6a8863526.

Change-Id: I97d53c27c1ca9e032d431b3aa7f915027d63ddc0
Related: OS#3014
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 769e049..55838fb 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -233,25 +233,31 @@
 	return rc;
 }
 
-static int write_ia_rest_uplink_sba(bitvec *dest, uint32_t fn, uint8_t alpha, uint8_t gamma, int8_t ta_idx,
-				    unsigned& wp)
+/* 3GPP TS 44.018 Table 10.5.2.16.1 < Packet Uplink Assignment > -- Single Block Allocation */
+static int write_ia_rest_uplink_sba(bitvec *dest, uint32_t fn, uint8_t alpha, uint8_t gamma)
 {
 	int rc = 0;
 
-	bitvec_write_field(dest, &wp, 0, 1); // Block Allocation: Single Block Allocation
+	SET_0(dest); /* Single Block Allocation */
+	rc = write_alpha_gamma(dest, alpha, gamma);
+	CHECK(rc);
 
-	if (alpha) {
-		bitvec_write_field(dest, &wp, 0x1, 1);   // ALPHA = present
-		bitvec_write_field(dest, &wp, alpha, 4);
-	} else
-		bitvec_write_field(dest, &wp, 0x0, 1);   // ALPHA = not present
+	/* A 'Timing Advance index' shall not be allocated at a Single Block allocation.
+	   A 'TBF Starting Time' shall be allocated at a Single Block allocation. */
+	SET_0(dest);
+	SET_1(dest);
 
-	bitvec_write_field(dest, &wp, gamma, 5);       // GAMMA power control parameter
-	write_tai(dest, wp, ta_idx);
-	bitvec_write_field(dest, &wp, 1, 1);         // TBF_STARTING_TIME_FLAG
-	bitvec_write_field(dest, &wp, (fn / (26 * 51)) % 32, 5); // T1'
-	bitvec_write_field(dest, &wp, fn % 51, 6);               // T3
-	bitvec_write_field(dest, &wp, fn % 26, 5);               // T2
+	rc = write_tbf_start_time(dest, fn);
+	CHECK(rc);
+
+	 /* No P0 nor PR_MODE */
+	SET_L(dest);
+
+	/* No Additions for R99 */
+	SET_L(dest);
+
+	 /* No Additions for Rel-6 */
+	SET_L(dest);
 
 	return rc;
 }
@@ -523,7 +529,8 @@
 			dest->cur_bit = wp;
 			rc = write_ia_rest_uplink_mba(as_ul_tbf(tbf), dest, usf, alpha, gamma);
 		} else {
-			rc = write_ia_rest_uplink_sba(dest, fn, alpha, gamma, ta_idx, wp);
+			dest->cur_bit = wp;
+			rc = write_ia_rest_uplink_sba(dest, fn, alpha, gamma);
 		}
 	}
 
diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp
index 4879424..822bd51 100644
--- a/tests/types/TypesTest.cpp
+++ b/tests/types/TypesTest.cpp
@@ -514,7 +514,7 @@
 				 0x23, /* TA */
 				 0x00, /* 0-length §10.5.2.21 Mobile Allocation */
 				 /* ETSI TS 44.018 §10.5.2.16 IA Rest Octets */
-				 0xc5, 0xd1, 0x08, 0x0b, 0x5b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, };
+				 0xc5, 0xd0, 0x80, 0xb5, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, };
 
 	check_imm_ass(NULL, false, GSM_L1_BURST_TYPE_ACCESS_0, res, sizeof(res), "ia_rest_uplink(SBA)");
 }
diff --git a/tests/types/TypesTest.ok b/tests/types/TypesTest.ok
index dd7dc4c..c6974d5 100644
--- a/tests/types/TypesTest.ok
+++ b/tests/types/TypesTest.ok
@@ -11,7 +11,7 @@
 [11] UL Immediate Assignment <ia_rest_uplink(MBA)>:
 	06 3f 10 0d 23 6d 0d 03 18 23 00 c8 02 1b a0 2b 2b 2b 2b 2b 2b 2b 2b 
 [11] UL Immediate Assignment <ia_rest_uplink(SBA)>:
-	06 3f 10 0d 23 6d 0d 03 18 23 00 c5 d1 08 0b 5b 2b 2b 2b 2b 2b 2b 2b 
+	06 3f 10 0d 23 6d 0d 03 18 23 00 c5 d0 80 b5 ab 2b 2b 2b 2b 2b 2b 2b 
 [11] UL Immediate Assignment <ia_rest_egprs_uplink(MBA)>:
 	06 3f 10 0d 23 6d 7f 03 18 23 00 46 97 40 0b 58 2b 2b 2b 2b 2b 2b 2b 
 [11] UL Immediate Assignment <ia_rest_egprs_uplink(SBA)>: