WIP: Support ANR procedures on MS with active TBF

TODO:
* General clean up
* Find out and fix why MS not resetting Neighbour List to BA(GPRS) when
  empty NC_Frequency_List is sent in Packet Measurement Order.
* Fix MS most of the time not sending Neighbour report for cells not
  present in SI2, probably due to waiting not enough time (increasing
  NC_REPORTING_PERIOD_T may help, but then problem in previous point above
  may show up more). Also maybe waiting for several reports before
  continuing may also help.
* Configurable/dynamic chunk list size currently hardcoded to 5.

Improvements/optimizations:
* Use FREQUENCY_DIFF in Add_Frequency for NC_Frequency_List to make
  it smaller and hence require less PAcketMeasurementOrder messages.
* Support Enchanced Packet Report message (need to signal support for it
  too).

Related: SYS#5303
Change-Id: I051d4fa90fe4ccc44ea691f8a3a487e97868e52c
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 0a4050f..3ece292 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -1815,3 +1815,46 @@
 	}
 	block->u.Packet_Cell_Change_Continue.CONTAINER_ID = container_id;
 }
+
+void write_packet_measurement_order(RlcMacDownlink_t *block, uint8_t poll, uint8_t rrbp,
+				    bool tfi_assigned, bool tfi_is_dl, uint8_t tfi,
+				    uint32_t tlli, uint8_t pmo_idx, uint8_t pmo_count,
+				    uint8_t nco, bool exist_nc, uint8_t non_drx_period,
+				    uint8_t nc_report_period_i, uint8_t nc_report_period_t,
+				    const NC_Frequency_list_t *NC_Frequency_list)
+{
+
+	block->PAYLOAD_TYPE = 0x1;  // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
+	block->RRBP         = rrbp;  // 0: N+13
+	block->SP           = poll; // RRBP field is valid?
+	block->USF          = 0x0;  // Uplink state flag
+
+	block->u.Packet_Measurement_Order.MESSAGE_TYPE = MT_PACKET_MEASUREMENT_ORDER;
+	block->u.Packet_Measurement_Order.PAGE_MODE    = 0x0;  // Normal Paging
+
+	if (!tfi_assigned) {
+		block->u.Packet_Measurement_Order.ID.UnionType = 0x01; // TLLI
+		block->u.Packet_Measurement_Order.ID.u.TLLI = tlli;
+	} else {
+		block->u.Packet_Measurement_Order.ID.UnionType = 0x00; // Global_TFI
+		block->u.Packet_Measurement_Order.ID.u.Global_TFI.UnionType = tfi_is_dl; // 0=UPLINK TFI, 1=DL TFI
+		if (tfi_is_dl)
+			block->u.Packet_Measurement_Order.ID.u.Global_TFI.u.DOWNLINK_TFI = tfi;
+		else
+			block->u.Packet_Measurement_Order.ID.u.Global_TFI.u.UPLINK_TFI = tfi;
+	}
+	block->u.Packet_Measurement_Order.PMO_INDEX = pmo_idx;
+	block->u.Packet_Measurement_Order.PMO_COUNT = pmo_count;
+	block->u.Packet_Measurement_Order.Exist_NC_Measurement_Parameters = 1;
+
+	block->u.Packet_Measurement_Order.NC_Measurement_Parameters.NETWORK_CONTROL_ORDER = nco;
+	block->u.Packet_Measurement_Order.NC_Measurement_Parameters.Exist_NC = exist_nc;
+	if (exist_nc) {
+		block->u.Packet_Measurement_Order.NC_Measurement_Parameters.NC_NON_DRX_PERIOD = non_drx_period;
+		block->u.Packet_Measurement_Order.NC_Measurement_Parameters.NC_REPORTING_PERIOD_I = nc_report_period_i;
+		block->u.Packet_Measurement_Order.NC_Measurement_Parameters.NC_REPORTING_PERIOD_T = nc_report_period_t;
+	}
+	block->u.Packet_Measurement_Order.NC_Measurement_Parameters.Exist_NC_FREQUENCY_LIST = NC_Frequency_list ? 1 : 0;
+	if (NC_Frequency_list)
+		block->u.Packet_Measurement_Order.NC_Measurement_Parameters.NC_Frequency_list = *NC_Frequency_list;
+}