encoding: implement handing of hopping parameters
The following test cases verify coding of the hopping parameters:
+ (RR) Immediate Assignment
- TC_pcuif_fh_imm_ass_ul_egprs,
- TC_pcuif_fh_imm_ass_ul,
- TC_pcuif_fh_imm_ass_dl,
+ (RLC/MAC) Packet Uplink/Downlink Assignment:
- TC_pcuif_fh_pkt_ass_ul,
- TC_pcuif_fh_pkt_ass_dl,
all of them pass with this (and the upcoming) change applied.
Change-Id: I8adc0cdb1b05a87b4df5d4bc196f6d381283a06f
Related: SYS#4868, OS#4547
diff --git a/src/encoding.cpp b/src/encoding.cpp
index ef21b61..ecf40de 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -467,8 +467,15 @@
bitvec_write_field(dest, &wp, pdch->ts_no, 3); // TN
bitvec_write_field(dest, &wp, pdch->tsc, 3); // TSC
- bitvec_write_field(dest, &wp, 0x00, 3); // spare (non-hopping RF channel configuraion)
- bitvec_write_field(dest, &wp, pdch->trx->arfcn, 10); // ARFCN
+ /* RF channel configuraion: hopping or non-hopping */
+ if (pdch->fh.enabled) {
+ bitvec_write_field(dest, &wp, 0x01, 1); /* direct encoding */
+ bitvec_write_field(dest, &wp, pdch->fh.maio, 6);
+ bitvec_write_field(dest, &wp, pdch->fh.hsn, 6);
+ } else {
+ bitvec_write_field(dest, &wp, 0x00, 3);
+ bitvec_write_field(dest, &wp, pdch->trx->arfcn, 10);
+ }
//10.5.2.30 Request Reference
if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
@@ -486,9 +493,16 @@
bitvec_write_field(dest, &wp,0x0,2); // spare
bitvec_write_field(dest, &wp,ta,6); // Timing Advance value
- // No mobile allocation in non-hopping systems.
- // A zero-length LV. Just write L=0.
- bitvec_write_field(dest, &wp,0,8);
+ /* 10.5.2.21 Mobile Allocation */
+ if (pdch->fh.enabled) {
+ bitvec_write_field(dest, &wp, pdch->fh.ma_oct_len, 8);
+ for (int i = 0; i < pdch->fh.ma_oct_len; i++)
+ bitvec_write_field(dest, &wp, pdch->fh.ma[i], 8);
+ } else {
+ // No mobile allocation in non-hopping systems.
+ // A zero-length LV. Just write L=0.
+ bitvec_write_field(dest, &wp, 0x00, 8);
+ }
OSMO_ASSERT(wp % 8 == 0);
@@ -536,6 +550,44 @@
return plen;
}
+/* Prepare to be encoded Frequency Parameters IE (see Table 12.8.1) */
+static void gen_freq_params(Frequency_Parameters_t *freq_params,
+ const struct gprs_rlcmac_tbf *tbf)
+{
+ const struct gprs_rlcmac_pdch *pdch;
+ Direct_encoding_1_t fh_params;
+
+ /* Check one PDCH, if it's hopping then all other should too */
+ pdch = tbf->pdch[tbf->first_ts];
+ OSMO_ASSERT(pdch != NULL);
+
+ /* Training Sequence Code */
+ freq_params->TSC = pdch->tsc;
+
+ /* If frequency hopping is not in use, encode a single ARFCN */
+ if (pdch == NULL || !pdch->fh.enabled) {
+ freq_params->UnionType = 0x00;
+ freq_params->u.ARFCN = tbf->trx->arfcn;
+ return;
+ }
+
+ /* Direct encoding 1 (see Table 12.8.1) */
+ freq_params->UnionType = 0x2;
+
+ /* HSN / MAIO */
+ fh_params.MAIO = pdch->fh.maio;
+ fh_params.GPRS_Mobile_Allocation.HSN = pdch->fh.hsn;
+ fh_params.GPRS_Mobile_Allocation.ElementsOf_RFL_NUMBER = 0;
+
+ /* Mobile Allocation bitmap */
+ fh_params.GPRS_Mobile_Allocation.UnionType = 0; /* MA bitmap */
+ fh_params.GPRS_Mobile_Allocation.u.MA.MA_LENGTH = pdch->fh.ma_oct_len; /* in bytes */
+ fh_params.GPRS_Mobile_Allocation.u.MA.MA_BitLength = pdch->fh.ma_bit_len; /* in bits */
+ memcpy(fh_params.GPRS_Mobile_Allocation.u.MA.MA_BITMAP, pdch->fh.ma, pdch->fh.ma_oct_len);
+
+ freq_params->u.Direct_encoding_1 = fh_params;
+}
+
/* Generate Packet Uplink Assignment as per 3GPP TS 44.060, section 11.2.29.
* NOTE: 'block' is expected to be zero-initialized by the caller. */
void Encoding::write_packet_uplink_assignment(
@@ -623,9 +675,7 @@
}
/* Frequency Parameters IE */
- fp->TSC = tbf->tsc(); // Training Sequence Code (TSC)
- fp->UnionType = 0x00; // Single ARFCN
- fp->u.ARFCN = tbf->trx->arfcn;
+ gen_freq_params(fp, tbf);
/* Dynamic allocation parameters */
da->USF_GRANULARITY = 0x00;
@@ -716,9 +766,7 @@
block->u.Packet_Downlink_Assignment.Exist_P0_and_BTS_PWR_CTRL_MODE = 0x0; // POWER CONTROL = off
block->u.Packet_Downlink_Assignment.Exist_Frequency_Parameters = 0x1; // Frequency Parameters = on
- block->u.Packet_Downlink_Assignment.Frequency_Parameters.TSC = tbf->tsc(); // Training Sequence Code (TSC)
- block->u.Packet_Downlink_Assignment.Frequency_Parameters.UnionType = 0x0; // ARFCN = on
- block->u.Packet_Downlink_Assignment.Frequency_Parameters.u.ARFCN = tbf->trx->arfcn; // ARFCN
+ gen_freq_params(&block->u.Packet_Downlink_Assignment.Frequency_Parameters, tbf);
block->u.Packet_Downlink_Assignment.Exist_DOWNLINK_TFI_ASSIGNMENT = 0x1; // DOWNLINK TFI ASSIGNMENT = on
block->u.Packet_Downlink_Assignment.DOWNLINK_TFI_ASSIGNMENT = tbf->tfi(); // TFI
diff --git a/src/pdch.h b/src/pdch.h
index e1e3688..1c0993f 100644
--- a/src/pdch.h
+++ b/src/pdch.h
@@ -106,6 +106,18 @@
void update_ta(uint8_t tai, uint8_t ta);
#endif
+ /* Frequency hopping parameters */
+ struct {
+ bool enabled;
+ /* 3GPP TS 45.002 HSN / MAIO (6 bit each) */
+ uint8_t hsn;
+ uint8_t maio;
+ /* 3GPP TS 44.018, 10.5.2.21 "Mobile Allocation" */
+ uint8_t ma_oct_len;
+ uint8_t ma_bit_len;
+ uint8_t ma[8];
+ } fh;
+
/* back pointers */
struct gprs_rlcmac_trx *trx;
uint8_t ts_no;