added multi antenna to pdcch

master
Ismael Gomez 8 years ago
parent 0a5a6245f1
commit 54d4d48f96

@ -76,9 +76,9 @@ typedef struct {
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
srslte_interp_lin_t srslte_interp_lin;
float rssi[SRSLTE_MAX_PORTS];
float rsrp[SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_PORTS];
float rssi[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS];
float rsrp[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS];
/* Use PSS for noise estimation in LS linear interpolation mode */
cf_t pss_signal[SRSLTE_PSS_LEN];
@ -86,6 +86,7 @@ typedef struct {
cf_t tmp_pss_noisy[SRSLTE_PSS_LEN];
srslte_chest_dl_noise_alg_t noise_alg;
int last_nof_antennas;
} srslte_chest_dl_t;
@ -120,7 +121,8 @@ SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q,
cf_t *input,
cf_t *ce,
uint32_t sf_idx,
uint32_t port_id);
uint32_t port_id,
uint32_t rxant_id);
SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q);

@ -63,12 +63,13 @@ typedef struct SRSLTE_API {
uint32_t nof_regs;
uint32_t nof_cce;
uint32_t max_bits;
uint32_t nof_rx_antennas;
srslte_regs_t *regs;
/* buffers */
cf_t *ce[SRSLTE_MAX_PORTS];
cf_t *symbols[SRSLTE_MAX_PORTS];
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT];
cf_t *symbols[SRSLTE_MAX_RXANT];
cf_t *x[SRSLTE_MAX_PORTS];
cf_t *d;
uint8_t *e;
@ -87,6 +88,11 @@ SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);
@ -113,6 +119,13 @@ SRSLTE_API int srslte_pdcch_extract_llr(srslte_pdcch_t *q,
uint32_t nsubframe,
uint32_t cfi);
SRSLTE_API int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q,
cf_t *sf_symbols[SRSLTE_MAX_RXANT],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT],
float noise_estimate,
uint32_t nsubframe,
uint32_t cfi);
/* Decoding functions: Try to decode a DCI message after calling srslte_pdcch_extract_llr */
SRSLTE_API int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
srslte_dci_msg_t *msg,

@ -311,7 +311,7 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id)
return rssi/nsymbols;
}
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id)
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id)
{
/* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
@ -331,24 +331,24 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
/* Estimate noise power */
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) {
q->noise_estimate[port_id] = estimate_noise_pilots(q, port_id);
q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id);
} else if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) {
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[port_id] = estimate_noise_pss(q, input, ce);
q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce);
}
} else {
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[port_id] = estimate_noise_empty_sc(q, input);
q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input);
}
}
}
/* Compute RSRP for the channel estimates in this port */
q->rsrp[port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
if (port_id == 0) {
/* compute rssi only for port 0 */
q->rssi[port_id] = srslte_chest_dl_rssi(q, input, port_id);
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
}
return 0;
@ -356,13 +356,14 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], uint32_t sf_idx, uint32_t nof_rx_antennas)
{
for (uint32_t rxant=0;rxant<nof_rx_antennas;rxant++) {
for (uint32_t rxant_id=0;rxant_id<nof_rx_antennas;rxant_id++) {
for (uint32_t port_id=0;port_id<q->cell.nof_ports;port_id++) {
if (srslte_chest_dl_estimate_port(q, input[rxant], ce[port_id][rxant], sf_idx, port_id)) {
if (srslte_chest_dl_estimate_port(q, input[rxant_id], ce[port_id][rxant_id], sf_idx, port_id, rxant_id)) {
return SRSLTE_ERROR;
}
}
}
q->last_nof_antennas = nof_rx_antennas;
return SRSLTE_SUCCESS;
}
@ -371,15 +372,20 @@ int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_
uint32_t port_id;
for (port_id=0;port_id<q->cell.nof_ports;port_id++) {
if (srslte_chest_dl_estimate_port(q, input, ce[port_id], sf_idx, port_id)) {
if (srslte_chest_dl_estimate_port(q, input, ce[port_id], sf_idx, port_id, 0)) {
return SRSLTE_ERROR;
}
}
q->last_nof_antennas = 1;
return SRSLTE_SUCCESS;
}
float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) {
return srslte_vec_acc_ff(q->noise_estimate, q->cell.nof_ports)/q->cell.nof_ports;
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
n += srslte_vec_acc_ff(q->noise_estimate[i], q->cell.nof_ports)/q->cell.nof_ports;
}
return n/q->last_nof_antennas;
}
float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
@ -392,20 +398,31 @@ float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
}
float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) {
return 4*q->rssi[0]/q->cell.nof_prb/SRSLTE_NRE;
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
n += 4*q->rssi[i][0]/q->cell.nof_prb/SRSLTE_NRE;
}
return n/q->last_nof_antennas;
}
/* q->rssi[0] is the average power in all RE in all symbol containing references for port 0 . q->rssi[0]/q->cell.nof_prb is the average power per PRB
* q->rsrp[0] is the average power of RE containing references only (for port 0).
*/
float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q) {
return q->cell.nof_prb*q->rsrp[0] / q->rssi[0];
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
n += q->cell.nof_prb*q->rsrp[i][0] / q->rssi[i][0];
}
return n/q->last_nof_antennas;
}
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
// return sum of power received from all tx ports
return srslte_vec_acc_ff(q->rsrp, q->cell.nof_ports);
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
n += srslte_vec_acc_ff(q->rsrp[i], q->cell.nof_ports)/q->cell.nof_ports;
}
return n/q->last_nof_antennas;
}

@ -161,7 +161,7 @@ int main(int argc, char **argv) {
struct timeval t[3];
gettimeofday(&t[1], NULL);
for (int j=0;j<100;j++) {
srslte_chest_dl_estimate_port(&est, input, ce, sf_idx, n_port);
srslte_chest_dl_estimate_port(&est, input, ce, sf_idx, n_port, 0);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);

@ -62,8 +62,12 @@ float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) {
/** Initializes the PDCCH transmitter and receiver */
int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
return srslte_pdcch_init_multi(q, regs, cell, 1);
}
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t i;
if (q != NULL &&
regs != NULL &&
@ -73,6 +77,7 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
bzero(q, sizeof(srslte_pdcch_t));
q->cell = cell;
q->regs = regs;
q->nof_rx_antennas = nof_rx_antennas;
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
@ -87,7 +92,7 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
goto clean;
}
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
// the maximum number of REGs (for CFI=3)
if (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) {
@ -117,17 +122,21 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
goto clean;
}
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->ce[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i]) {
goto clean;
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int j=0;j<q->nof_rx_antennas;j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i][j]) {
goto clean;
}
}
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->x[i]) {
goto clean;
}
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->symbols[i]) {
}
for (int j=0;j<q->nof_rx_antennas;j++) {
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->symbols[j]) {
goto clean;
}
}
@ -142,7 +151,6 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
}
void srslte_pdcch_free(srslte_pdcch_t *q) {
int i;
if (q->e) {
free(q->e);
@ -153,19 +161,22 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
if (q->d) {
free(q->d);
}
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (q->ce[i]) {
free(q->ce[i]);
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
if (q->x[i]) {
free(q->x[i]);
}
if (q->symbols[i]) {
free(q->symbols[i]);
}
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->symbols[j]) {
free(q->symbols[j]);
}
}
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
srslte_sequence_free(&q->seq[i]);
}
@ -379,13 +390,27 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
int cnt=0;
int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
uint32_t nsubframe, uint32_t cfi)
{
cf_t *_sf_symbols[SRSLTE_MAX_RXANT];
cf_t *_ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT];
_sf_symbols[0] = sf_symbols;
for (int i=0;i<q->cell.nof_ports;i++) {
_ce[i][0] = ce[i];
}
return srslte_pdcch_extract_llr_multi(q, _sf_symbols, _ce, noise_estimate, nsubframe, cfi);
}
/** Extracts the LLRs from srslte_dci_location_t location of the subframe and stores them in the srslte_pdcch_t structure.
* DCI messages can be extracted from this location calling the function srslte_pdcch_decode_msg().
* Every time this function is called (with a different location), the last demodulated symbols are overwritten and
* new messages from other locations can be decoded
*/
int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
uint32_t nsubframe, uint32_t cfi) {
int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], float noise_estimate,
uint32_t nsubframe, uint32_t cfi)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -415,27 +440,29 @@ int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLT
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */
int n = srslte_regs_pdcch_get(q->regs, sf_symbols, q->symbols[0]);
if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret;
}
/* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) {
n = srslte_regs_pdcch_get(q->regs, ce[i], q->ce[i]);
for (int j=0;j<q->nof_rx_antennas;j++) {
int n = srslte_regs_pdcch_get(q->regs, sf_symbols[j], q->symbols[j]);
if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret;
}
/* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) {
n = srslte_regs_pdcch_get(q->regs, ce[i][j], q->ce[i][j]);
if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret;
}
}
}
/* in control channels, only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, nof_symbols, noise_estimate/2);
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, nof_symbols, noise_estimate/2);
} else {
srslte_predecoding_diversity(q->symbols[0], q->ce, x, q->cell.nof_ports, nof_symbols);
srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols);
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
}

@ -87,7 +87,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
goto clean_exit;
}
if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) {
if (srslte_pdcch_init_multi(&q->pdcch, &q->regs, q->cell, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDCCH object\n");
goto clean_exit;
}
@ -272,11 +272,11 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], u
return ret;
}
cf_t *ce0[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce0[i] = q->ce[i][0];
}
if (srslte_pdcch_extract_llr(&q->pdcch, q->sf_symbols[0], ce0, srslte_chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) {
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
// Uncoment next line to do ZF by default in pdsch_ue example
//float noise_estimate = 0;
if (srslte_pdcch_extract_llr_multi(&q->pdcch, q->sf_symbols, q->ce, noise_estimate, sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return SRSLTE_ERROR;
}
@ -311,9 +311,6 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], u
q->nof_detected++;
// Uncoment next line to do ZF by default in pdsch_ue example
//float noise_estimate = 0;
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
ret = srslte_pdsch_decode_multi(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,

Loading…
Cancel
Save