Set Alpha and Gamma at assingment messages for power control

The initial power control value Alpha must be set in SI13.
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index f7ec847..64bbe75 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -1161,7 +1161,8 @@
 int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
 	uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc,
 	uint8_t tfi, uint8_t usf, uint32_t tlli,
-	uint8_t polling, uint32_t fn, uint8_t single_block)
+	uint8_t polling, uint32_t fn, uint8_t single_block, uint8_t alpha,
+	uint8_t gamma)
 {
 	unsigned wp = 0;
 	uint8_t plen;
@@ -1215,8 +1216,13 @@
 		bitvec_write_field(dest, wp,0x1,1);   // switch TFI   : on
 		bitvec_write_field(dest, wp,tfi,5);   // TFI
 		bitvec_write_field(dest, wp,0x0,1);   // RLC acknowledged mode
-		bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
-		bitvec_write_field(dest, wp,0x0,5);   // GAMMA power control parameter
+		if (alpha) {
+			bitvec_write_field(dest, wp,0x1,1);   // ALPHA = present
+			bitvec_write_field(dest, wp,alpha,4);   // ALPHA
+		} else {
+			bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
+		}
+		bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
 		bitvec_write_field(dest, wp,polling,1);   // Polling Bit
 		bitvec_write_field(dest, wp,!polling,1);   // TA_VALID ???
 		bitvec_write_field(dest, wp,0x1,1);   // switch TIMING_ADVANCE_INDEX = on
@@ -1241,9 +1247,12 @@
 		bitvec_write_field(dest, wp, 0, 2);    // "0" Packet Uplink Assignment
 		if (single_block) {
 			bitvec_write_field(dest, wp, 0, 1);    // Block Allocation : Single Block Allocation
-			bitvec_write_field(dest, wp, 1, 1);   // "1" Alpha : Present
-			bitvec_write_field(dest, wp, 0, 4);    // Alpha
-			bitvec_write_field(dest, wp, 0, 5);    // Gamma
+			if (alpha) {
+				bitvec_write_field(dest, wp,0x1,1);   // ALPHA = present
+				bitvec_write_field(dest, wp,alpha,4);   // ALPHA = present
+			} else
+				bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
+			bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
 			bitvec_write_field(dest, wp, 0, 1);    // TIMING_ADVANCE_INDEX_FLAG
 			bitvec_write_field(dest, wp, 1, 1);    // TBF_STARTING_TIME_FLAG
 			bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
@@ -1259,9 +1268,12 @@
 			bitvec_write_field(dest, wp, 0, 1);   // "0" power control: Not Present
 			bitvec_write_field(dest, wp, bts->initial_cs-1, 2);    // CHANNEL_CODING_COMMAND 
 			bitvec_write_field(dest, wp, 1, 1);    // TLLI_BLOCK_CHANNEL_CODING
-			bitvec_write_field(dest, wp, 1, 1);   // "1" Alpha : Present
-			bitvec_write_field(dest, wp, 0, 4);    // Alpha
-			bitvec_write_field(dest, wp, 0, 5);    // Gamma
+			if (alpha) {
+				bitvec_write_field(dest, wp,0x1,1);   // ALPHA = present
+				bitvec_write_field(dest, wp,alpha,4);   // ALPHA
+			} else
+				bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
+			bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
 			bitvec_write_field(dest, wp, 0, 1);    // TIMING_ADVANCE_INDEX_FLAG
 			bitvec_write_field(dest, wp, 0, 1);    // TBF_STARTING_TIME_FLAG
 		}
@@ -1273,7 +1285,8 @@
 /* generate uplink assignment */
 void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
 	uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
-	struct gprs_rlcmac_tbf *tbf, uint8_t poll)
+	struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
+	uint8_t gamma)
 {
 	// TODO We should use our implementation of encode RLC/MAC Control messages.
 	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
@@ -1326,12 +1339,18 @@
 
 	bitvec_write_field(dest, wp,0x0,1); //
 	bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
-	bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
+	if (alpha || gamma) {
+		bitvec_write_field(dest, wp,0x1,1); // Timeslot Allocation with Power Control
+		bitvec_write_field(dest, wp,alpha,4);   // ALPHA
+	} else
+		bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
 	
 	for (ts = 0; ts < 8; ts++) {
 		if (tbf->pdch[ts]) {
 			bitvec_write_field(dest, wp,0x1,1); // USF_TN(i): on
 			bitvec_write_field(dest, wp,tbf->dir.ul.usf[ts],3); // USF_TN(i)
+			if (alpha || gamma)
+				bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
 		} else
 			bitvec_write_field(dest, wp,0x0,1); // USF_TN(i): off
 	}
@@ -1341,7 +1360,8 @@
 
 /* generate downlink assignment */
 void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
-	uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll)
+	uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
+	uint8_t alpha, uint8_t gamma)
 {
 	// Packet downlink assignment TS 44.060 11.2.7
 
@@ -1385,14 +1405,14 @@
 	block->u.Packet_Downlink_Assignment.DOWNLINK_TFI_ASSIGNMENT        = tbf->tfi; // TFI
 
 	block->u.Packet_Downlink_Assignment.Exist_Power_Control_Parameters = 0x1;   // Power Control Parameters = on
-	block->u.Packet_Downlink_Assignment.Power_Control_Parameters.ALPHA = 0x0;   // ALPHA
+	block->u.Packet_Downlink_Assignment.Power_Control_Parameters.ALPHA = alpha;   // ALPHA
 
 	for (tn = 0; tn < 8; tn++)
 	{
 		if (tbf->pdch[tn])
 		{
 			block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].Exist    = 0x1; // Slot[i] = on
-			block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].GAMMA_TN = 0x0; // GAMMA_TN
+			block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].GAMMA_TN = gamma; // GAMMA_TN
 		}
 		else
 		{
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index e7a68a4..4643991 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -83,6 +83,7 @@
 		struct gprs_rlcmac_tbf *tbf, uint32_t cust);
 	uint32_t alloc_algorithm_curst; /* options to customize algorithm */
 	uint8_t force_two_phase;
+	uint8_t alpha, gamma;
 };
 
 extern struct gprs_rlcmac_bts *gprs_rlcmac_bts;
@@ -292,14 +293,16 @@
 int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, 
         uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, 
         uint8_t tfi, uint8_t usf, uint32_t tlli, uint8_t polling,
-	uint32_t fn, uint8_t single_block);
+	uint32_t fn, uint8_t single_block, uint8_t alpha, uint8_t gamma);
 
 void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
 	uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli, 
-	struct gprs_rlcmac_tbf *tbf, uint8_t poll);
+	struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
+	uint8_t gamma);
 
 void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
-	uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll);
+	uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
+	uint8_t alpha, uint8_t gamma);
 
 
 
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index 8bb1df6..b6d5062 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -946,6 +946,7 @@
 struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
 	struct gprs_rlcmac_tbf *tbf, uint32_t fn)
 {
+	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
 	struct msgb *msg;
 	struct gprs_rlcmac_tbf *new_tbf;
 
@@ -990,7 +991,8 @@
 		"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 	write_packet_uplink_assignment(ass_vec, tbf->tfi,
 		(tbf->direction == GPRS_RLCMAC_DL_TBF), tbf->tlli,
-		tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL);
+		tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL, bts->alpha,
+		bts->gamma);
 	bitvec_pack(ass_vec, msgb_put(msg, 23));
 	RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
 	LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n");
@@ -1081,11 +1083,13 @@
 	if (sb)
 		plen = write_immediate_assignment(immediate_assignment, 0, ra,
 			Fn, qta >> 2, bts->trx[trx].arfcn, ts,
-			bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1);
+			bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1,
+			bts->alpha, bts->gamma);
 	else
 		plen = write_immediate_assignment(immediate_assignment, 0, ra,
 			Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc,
-			tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0);
+			tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0,
+			bts->alpha, bts->gamma);
 	pcu_l1if_tx_agch(immediate_assignment, plen);
 	bitvec_free(immediate_assignment);
 
@@ -1611,6 +1615,7 @@
 struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
 	struct gprs_rlcmac_tbf *tbf, uint32_t fn)
 {
+	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
 	struct msgb *msg;
 	struct gprs_rlcmac_tbf *new_tbf;
 	int poll_ass_dl = POLLING_ASSIGNMENT_DL;
@@ -1670,7 +1675,7 @@
 	RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
 	write_packet_downlink_assignment(mac_control_block, tbf->tfi,
 		(tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf,
-		poll_ass_dl);
+		poll_ass_dl, bts->alpha, bts->gamma);
 	LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
 	encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
 	LOGPC(DCSN1, LOGL_NOTICE, "\n");
@@ -1698,12 +1703,18 @@
 static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll,
 	char *imsi)
 {
+	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+	int plen;
+
 	LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u TLLI: 0x%08x Immediate Assignment Downlink (PCH)\n", tbf->tfi, tbf->tlli);
 	bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
 	bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 	/* use request reference that has maximum distance to current time,
 	 * so the assignment will not conflict with possible RACH requests. */
-	int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn, 0);
+	plen = write_immediate_assignment(immediate_assignment, 1, 125,
+		(tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta,
+		tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll,
+		tbf->poll_fn, 0, bts->alpha, bts->gamma);
 	pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
 	bitvec_free(immediate_assignment);
 }
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 2392152..ba31ca7 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -153,6 +153,7 @@
 	bts->n3101 = 10;
 	bts->n3103 = 4;
 	bts->n3105 = 8;
+	bts->alpha = 10; /* a = 1.0 */
 
 	msgb_set_talloc_ctx(tall_pcu_ctx);
 
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 8d5b47b..d7c2c2c 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -94,6 +94,8 @@
 		vty_out(vty, " alloc-algorithm b%s", VTY_NEWLINE);
 	if (bts->force_two_phase)
 		vty_out(vty, " two-phase-access%s", VTY_NEWLINE);
+	vty_out(vty, " alpha %d%s", bts->alpha, VTY_NEWLINE);
+	vty_out(vty, " gamma %d%s", bts->gamma * 2, VTY_NEWLINE);
 
 }
 
@@ -110,9 +112,9 @@
 
 DEFUN(cfg_pcu_fc_interval,
       cfg_pcu_fc_interval_cmd,
-      "flow-control-interval <1..10>",
+      "flow-control-interval <1-10>",
       "Interval between sending subsequent Flow Control PDUs\n"
-      "Tiem in seconds\n")
+      "Interval time in seconds\n")
 {
 	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
 
@@ -234,6 +236,33 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_pcu_alpha,
+      cfg_pcu_alpha_cmd,
+      "alpha <0-10>",
+      "Alpha parameter for MS power control in units of 0.1 (see TS 05.08) "
+      "NOTE: Be sure to set Alpha value at System information 13 too.\n"
+      "Alpha in units of 0.1\n")
+{
+	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+
+	bts->alpha = atoi(argv[0]);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_gamma,
+      cfg_pcu_gamma_cmd,
+      "gamma <0-62>",
+      "Gamma parameter for MS power control in units of dB (see TS 05.08)\n"
+      "Gamma in even unit of dBs\n")
+{
+	struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+
+	bts->gamma = atoi(argv[0]) / 2;
+
+	return CMD_SUCCESS;
+}
+
 static const char pcu_copyright[] =
 	"Copyright (C) 2012 by ...\r\n"
 	"License GNU GPL version 2 or later\r\n"
@@ -266,6 +295,8 @@
 	install_element(PCU_NODE, &cfg_pcu_alloc_cmd);
 	install_element(PCU_NODE, &cfg_pcu_two_phase_cmd);
 	install_element(PCU_NODE, &cfg_pcu_fc_interval_cmd);
+	install_element(PCU_NODE, &cfg_pcu_alpha_cmd);
+	install_element(PCU_NODE, &cfg_pcu_gamma_cmd);
 	install_element(PCU_NODE, &ournode_end_cmd);
 
 	return 0;