rxqual: Begin to implement the rxqual calculation
* Make num_biterr 16bit because the API is 16bit. * Add the num_bits to count the bits transferred. * Re-order and add manual padding due the increase in size. * Add the bits to struct rx_meas_stat, increment and reset them. * Calculation for the sub_rxqual is missing, so is DTX code in general * Calculation for TCH/F, TCH/H in speech mode might be wrong
This commit is contained in:
parent
08bc45147b
commit
20971da499
|
@ -100,10 +100,14 @@ struct l1ctl_info_dl {
|
|||
|
||||
uint32_t frame_nr;
|
||||
|
||||
uint16_t num_biterr; /* number of estimated bit errors (BER) */
|
||||
uint16_t num_bits; /* number of transfered bits */
|
||||
|
||||
uint8_t rx_level; /* 0 .. 63 in typical GSM notation (dBm+110) */
|
||||
uint8_t snr; /* Signal/Noise Ration (dB) */
|
||||
uint8_t num_biterr;
|
||||
|
||||
uint8_t fire_crc;
|
||||
uint8_t padding[1];
|
||||
|
||||
uint8_t payload[0];
|
||||
} __attribute__((packed));
|
||||
|
|
|
@ -45,6 +45,7 @@ struct rx_meas_stat {
|
|||
uint32_t frames;
|
||||
uint32_t snr;
|
||||
uint32_t berr;
|
||||
uint32_t bits;
|
||||
uint32_t rxlev;
|
||||
|
||||
/* counters loss criterion */
|
||||
|
|
|
@ -186,6 +186,7 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
|
|||
meas->frames++;
|
||||
meas->snr += dl->snr;
|
||||
meas->berr += dl->num_biterr;
|
||||
meas->bits += dl->num_bits;
|
||||
meas->rxlev += dl->rx_level;
|
||||
|
||||
/* counting loss criteria */
|
||||
|
|
|
@ -470,7 +470,7 @@ static int gsm322_sync_to_cell(struct gsm322_cellsel *cs,
|
|||
cs->ccch_mode = CCCH_MODE_NONE;
|
||||
}
|
||||
|
||||
meas->frames = meas->snr = meas->berr = meas->rxlev = 0;
|
||||
meas->frames = meas->snr = meas->berr = meas->bits = meas->rxlev = 0;
|
||||
cs->rxlev_dbm = cs->rxlev_count = 0;
|
||||
|
||||
cs->neighbour = neighbour;
|
||||
|
|
|
@ -98,6 +98,33 @@ static int gsm48_rr_rel_cnf(struct osmocom_ms *ms, struct msgb *msg);
|
|||
|
||||
#define MIN(a, b) ((a < b) ? a : b)
|
||||
|
||||
static int calc_rxqual(struct rx_meas_stat *stat)
|
||||
{
|
||||
uint32_t qual;
|
||||
|
||||
/* no bits transferred, so no error */
|
||||
if (stat->bits == 0)
|
||||
return 0;
|
||||
|
||||
qual = (stat->berr * 500) / stat->bits;
|
||||
if (qual == 0)
|
||||
return 0;
|
||||
if (qual == 1)
|
||||
return 1;
|
||||
if (qual < 4)
|
||||
return 2;
|
||||
if (qual < 8)
|
||||
return 3;
|
||||
if (qual < 16)
|
||||
return 4;
|
||||
if (qual < 32)
|
||||
return 5;
|
||||
if (qual < 64)
|
||||
return 6;
|
||||
|
||||
return 7;
|
||||
}
|
||||
|
||||
/* decode "Power Command" (10.5.2.28) and (10.5.2.28a) */
|
||||
static int gsm48_decode_power_cmd_acc(struct gsm48_power_cmd *pc,
|
||||
uint8_t *power_level, uint8_t *atc)
|
||||
|
@ -667,7 +694,7 @@ static void timeout_rr_meas(void *arg)
|
|||
gsm48_rr_tx_meas_rep(rr->ms);
|
||||
|
||||
restart:
|
||||
meas->frames = meas->snr = meas->berr = meas->rxlev = 0;
|
||||
meas->frames = meas->snr = meas->berr = meas->bits = meas->rxlev = 0;
|
||||
start_rr_t_meas(rr, 1, 0);
|
||||
}
|
||||
|
||||
|
@ -2757,7 +2784,8 @@ static int gsm48_rr_tx_meas_rep(struct osmocom_ms *ms)
|
|||
meas_valid = 1;
|
||||
serv_rxlev_full = serv_rxlev_sub =
|
||||
(meas->rxlev + (meas->frames / 2)) / meas->frames;
|
||||
serv_rxqual_full = serv_rxqual_sub = 0; // FIXME
|
||||
serv_rxqual_full = calc_rxqual(meas);
|
||||
serv_rxqual_sub = 0; // FIXME
|
||||
}
|
||||
|
||||
memset(&rxlev_nc, 0, sizeof(rxlev_nc));
|
||||
|
@ -2987,7 +3015,7 @@ static int gsm48_rr_activate_channel(struct osmocom_ms *ms,
|
|||
memset(s->si5b_msg, 0, sizeof(s->si5b_msg));
|
||||
memset(s->si5t_msg, 0, sizeof(s->si5t_msg));
|
||||
}
|
||||
meas->frames = meas->snr = meas->berr = meas->rxlev = 0;
|
||||
meas->frames = meas->snr = meas->berr = meas->bits = meas->rxlev = 0;
|
||||
rr->meas.nc_num = 0;
|
||||
stop_rr_t_meas(rr);
|
||||
start_rr_t_meas(rr, 1, 0);
|
||||
|
|
|
@ -53,6 +53,9 @@
|
|||
|
||||
#include <l1ctl_proto.h>
|
||||
|
||||
/* From GSM 05.01 7 Coding and interleaving. Coded bits per block */
|
||||
#define BIT_LEN_SDCCH 456 /* and for BIT_LEN_SACCH */
|
||||
|
||||
struct l1s_rxnb_state {
|
||||
struct l1s_meas_hdr meas[4];
|
||||
|
||||
|
@ -112,7 +115,6 @@ static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
|
|||
/* 4th burst, get frame data */
|
||||
if (dsp_api.db_r->d_burst_d == 3) {
|
||||
uint8_t i;
|
||||
uint16_t num_biterr;
|
||||
uint32_t avg_snr = 0;
|
||||
int32_t avg_dbm8 = 0;
|
||||
|
||||
|
@ -141,11 +143,8 @@ static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
|
|||
rxnb.dl->snr = avg_snr / 4;
|
||||
rxnb.dl->rx_level = dbm2rxlev(avg_dbm8 / (8*4));
|
||||
|
||||
num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
|
||||
if (num_biterr > 0xff)
|
||||
rxnb.dl->num_biterr = 0xff;
|
||||
else
|
||||
rxnb.dl->num_biterr = num_biterr;
|
||||
rxnb.dl->num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
|
||||
rxnb.dl->num_bits = BIT_LEN_SDCCH;
|
||||
|
||||
rxnb.dl->fire_crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
|
||||
|
||||
|
|
|
@ -55,6 +55,12 @@
|
|||
|
||||
#include <l1ctl_proto.h>
|
||||
|
||||
/* From GSM 05.01 7 Coding and interleaving. Coded bits per block */
|
||||
#define BIT_LEN_FACCHF 456
|
||||
#define BIT_LEN_SACCH 456 /* and for BIT_LEN_SDCCH */
|
||||
#define BIT_LEN_TCHFS 378
|
||||
#define BIT_LEN_TCHHS 211
|
||||
|
||||
|
||||
/* This computes various parameters both for the DSP and for
|
||||
* our logic. Not all are used all the time, but it's easier
|
||||
|
@ -211,7 +217,6 @@ static int l1s_tch_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
|
|||
struct msgb *msg;
|
||||
struct l1ctl_info_dl *dl;
|
||||
struct l1ctl_data_ind *di;
|
||||
uint16_t num_biterr;
|
||||
uint32_t avg_snr = 0;
|
||||
int32_t avg_dbm8 = 0;
|
||||
int i, n;
|
||||
|
@ -245,12 +250,8 @@ static int l1s_tch_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
|
|||
dl->rx_level = dbm2rxlev(avg_dbm8 / (8*n));
|
||||
|
||||
/* Errors & CRC status */
|
||||
num_biterr = dsp_api.ndb->a_fd[2] & 0xffff;
|
||||
if (num_biterr > 0xff)
|
||||
dl->num_biterr = 0xff;
|
||||
else
|
||||
dl->num_biterr = num_biterr;
|
||||
|
||||
dl->num_biterr = dsp_api.ndb->a_fd[2] & 0xffff;
|
||||
dl->num_bits = BIT_LEN_FACCHF;
|
||||
dl->fire_crc = ((dsp_api.ndb->a_fd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
|
||||
|
||||
/* Update rx level for pm report */
|
||||
|
@ -309,6 +310,9 @@ static int l1s_tch_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
|
|||
}
|
||||
|
||||
dl = (struct l1ctl_info_dl *) msgb_put(msg, sizeof(*dl));
|
||||
/* FIXE: verify this for different audio modes */
|
||||
dl->num_biterr = traffic_buf[2] & 0xffff;
|
||||
dl->num_bits = tch_f_hn ? BIT_LEN_TCHFS : BIT_LEN_TCHHS;
|
||||
ti = (struct l1ctl_traffic_ind *) msgb_put(msg, sizeof(*ti));
|
||||
|
||||
/* Copy actual data, skipping the information block [0,1,2] */
|
||||
|
@ -618,7 +622,6 @@ static int l1s_tch_a_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
|
|||
/* Last burst, read data & send to the up layer */
|
||||
if ((burst_id == 3) && (dsp_api.ndb->a_cd[0] & (1<<B_BLUD))) {
|
||||
unsigned int i;
|
||||
uint16_t num_biterr;
|
||||
uint32_t avg_snr = 0;
|
||||
int32_t avg_dbm8 = 0;
|
||||
|
||||
|
@ -630,12 +633,8 @@ static int l1s_tch_a_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
|
|||
rx_tch_a.dl->snr = avg_snr / 4;
|
||||
rx_tch_a.dl->rx_level = dbm2rxlev(avg_dbm8 / (8*4));
|
||||
|
||||
num_biterr = dsp_api.ndb->a_cd[2];
|
||||
if (num_biterr > 0xff)
|
||||
rx_tch_a.dl->num_biterr = 0xff;
|
||||
else
|
||||
rx_tch_a.dl->num_biterr = num_biterr;
|
||||
|
||||
rx_tch_a.dl->num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
|
||||
rx_tch_a.dl->num_bits = BIT_LEN_SACCH;
|
||||
rx_tch_a.dl->fire_crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
|
||||
|
||||
/* Update rx level for pm report */
|
||||
|
|
Loading…
Reference in New Issue