Set Alpha and Gamma at assingment messages for power control

The initial power control value Alpha must be set in SI13.
This commit is contained in:
Andreas Eversberg 2012-09-27 09:20:45 +02:00
parent df4d20e95b
commit aafcbbb252
5 changed files with 90 additions and 24 deletions

View File

@ -1161,7 +1161,8 @@ struct msgb *gprs_rlcmac_send_packet_paging_request(
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 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
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 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
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 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
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 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
/* 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 @@ void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
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 @@ void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
/* 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 @@ void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
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
{

View File

@ -83,6 +83,7 @@ struct gprs_rlcmac_bts {
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 gprs_rlcmac_rcv_block(uint8_t trx, uint8_t ts, uint8_t *data, uint8_t len,
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);

View File

@ -946,6 +946,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts,
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 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
"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 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
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 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
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 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
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 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
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);
}

View File

@ -153,6 +153,7 @@ int main(int argc, char *argv[])
bts->n3101 = 10;
bts->n3103 = 4;
bts->n3105 = 8;
bts->alpha = 10; /* a = 1.0 */
msgb_set_talloc_ctx(tall_pcu_ctx);

View File

@ -94,6 +94,8 @@ static int config_write_pcu(struct vty *vty)
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,
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 @@ DEFUN(cfg_pcu_no_two_phase,
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 @@ int pcu_vty_init(const struct log_info *cat)
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;