mirror of https://github.com/PentHertz/srsLTE.git
added support for multiple rx antennas to pdsch. Working in matlab for 1/2 ports tx diversity
This commit is contained in:
parent
462d222fd2
commit
0bd749aa29
|
@ -8,10 +8,10 @@
|
|||
recordedSignal=[];
|
||||
|
||||
Npackets = 1;
|
||||
SNR_values = 56;%linspace(2,6,10);
|
||||
SNR_values = 50;%linspace(8,11,5);
|
||||
|
||||
%% Choose RMC
|
||||
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.5',[1;0;0;1]);
|
||||
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.12',[1;0;0;1]);
|
||||
waveform = sum(waveform,2);
|
||||
|
||||
if ~isempty(recordedSignal)
|
||||
|
@ -105,9 +105,6 @@ for snr_idx=1:length(SNR_values)
|
|||
subframe_rx);
|
||||
else
|
||||
dec2 = 1;
|
||||
end
|
||||
if (~dec2)
|
||||
fprintf('Error in sf=%d\n',sf_idx);
|
||||
end
|
||||
decoded_srslte(snr_idx) = decoded_srslte(snr_idx)+dec2;
|
||||
end
|
||||
|
|
|
@ -107,8 +107,9 @@ SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q,
|
|||
|
||||
SRSLTE_API int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q,
|
||||
cf_t *input[SRSLTE_MAX_RXANT],
|
||||
cf_t *ce[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS],
|
||||
uint32_t sf_idx);
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT],
|
||||
uint32_t sf_idx,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
|
||||
cf_t *input,
|
||||
|
|
|
@ -55,12 +55,14 @@ typedef struct {
|
|||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
|
||||
uint32_t nof_rx_antennas;
|
||||
|
||||
uint32_t max_re;
|
||||
|
||||
/* buffers */
|
||||
// void buffers are shared for tx and rx
|
||||
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;
|
||||
void *e;
|
||||
|
@ -78,6 +80,10 @@ typedef struct SRSLTE_API {
|
|||
SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_init_multi(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
|
||||
|
@ -112,6 +118,15 @@ SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
uint16_t rnti,
|
||||
uint8_t *data);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols[SRSLTE_MAX_RXANT],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT],
|
||||
float noise_estimate,
|
||||
uint16_t rnti,
|
||||
uint8_t *data);
|
||||
|
||||
SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q);
|
||||
|
||||
SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q);
|
||||
|
|
|
@ -354,11 +354,12 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t nof_rx_antennas)
|
||||
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 port_id=0;port_id<q->cell.nof_ports;port_id++) {
|
||||
if (srslte_chest_dl_estimate_port(q, input[rxant], ce[rxant][port_id], sf_idx, port_id)) {
|
||||
printf("rxant=%d, port=%d, input=0x%x, ce=0x%x\n", rxant, port_id, input[rxant], ce[port_id][rxant]);
|
||||
if (srslte_chest_dl_estimate_port(q, input[rxant], ce[port_id][rxant], sf_idx, port_id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,13 +202,20 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols,
|
|||
return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false);
|
||||
}
|
||||
|
||||
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell)
|
||||
{
|
||||
return srslte_pdsch_init_multi(q, cell, 1);
|
||||
}
|
||||
|
||||
/** Initializes the PDCCH transmitter and receiver */
|
||||
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
|
||||
int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_rx_antennas)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
int i;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell) &&
|
||||
nof_rx_antennas <= SRSLTE_MAX_RXANT)
|
||||
{
|
||||
|
||||
bzero(q, sizeof(srslte_pdsch_t));
|
||||
|
@ -216,6 +223,7 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
|
|||
|
||||
q->cell = cell;
|
||||
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
|
||||
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
|
||||
q->cell.nof_prb, q->max_re);
|
||||
|
@ -241,16 +249,20 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
|
|||
}
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
q->ce[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce[i]) {
|
||||
goto clean;
|
||||
}
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->symbols[i]) {
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->symbols[j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
@ -280,17 +292,20 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
|
|||
free(q->d);
|
||||
}
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (q->ce[i]) {
|
||||
free(q->ce[i]);
|
||||
}
|
||||
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->ce[i][j]) {
|
||||
free(q->ce[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->symbols[j]) {
|
||||
free(q->symbols[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if (q->users) {
|
||||
for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) {
|
||||
if (q->users[u]) {
|
||||
|
@ -363,13 +378,28 @@ void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
|
|||
}
|
||||
}
|
||||
|
||||
/** Decodes the PDSCH from the received symbols
|
||||
*/
|
||||
int srslte_pdsch_decode(srslte_pdsch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
|
||||
uint16_t rnti, uint8_t *data)
|
||||
{
|
||||
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_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, data);
|
||||
}
|
||||
|
||||
/** Decodes the PDSCH from the received symbols
|
||||
*/
|
||||
int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], float noise_estimate,
|
||||
uint16_t rnti, uint8_t *data)
|
||||
{
|
||||
|
||||
/* Set pointers for layermapping & precoding */
|
||||
uint32_t i, n;
|
||||
|
@ -391,31 +421,31 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
}
|
||||
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
|
||||
|
||||
/* extract symbols */
|
||||
n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx);
|
||||
if (n != cfg->nbits.nof_re) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* extract channel estimates */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
n = srslte_pdsch_get(q, ce[i], q->ce[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx);
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
/* extract symbols */
|
||||
n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx);
|
||||
if (n != cfg->nbits.nof_re) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* extract channel estimates */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
n = srslte_pdsch_get(q, ce[i][j], q->ce[i][j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx);
|
||||
if (n != cfg->nbits.nof_re) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: 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, cfg->nbits.nof_re, noise_estimate);
|
||||
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits.nof_re, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(q->symbols[0], q->ce, x, q->cell.nof_ports,
|
||||
cfg->nbits.nof_re);
|
||||
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports,
|
||||
cfg->nbits.nof_re / q->cell.nof_ports);
|
||||
srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->cell.nof_ports, q->nof_rx_antennas, cfg->nbits.nof_re);
|
||||
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports);
|
||||
}
|
||||
|
||||
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||||
|
|
|
@ -55,7 +55,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
srslte_ofdm_t ofdm_rx;
|
||||
srslte_pdsch_t pdsch;
|
||||
srslte_chest_dl_t chest;
|
||||
cf_t *input_fft;
|
||||
cf_t *input_fft[SRSLTE_MAX_RXANT];
|
||||
srslte_pdsch_cfg_t cfg;
|
||||
srslte_softbuffer_rx_t softbuffer;
|
||||
uint32_t rnti32;
|
||||
|
@ -93,7 +93,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
return;
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init(&pdsch, cell)) {
|
||||
|
||||
const size_t ndims = mxGetNumberOfDimensions(INPUT);
|
||||
uint32_t nof_antennas = 1;
|
||||
if (ndims >= 3) {
|
||||
const mwSize *dims = mxGetDimensions(INPUT);
|
||||
nof_antennas = dims[2];
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init_multi(&pdsch, cell, nof_antennas)) {
|
||||
mexErrMsgTxt("Error initiating PDSCH\n");
|
||||
return;
|
||||
}
|
||||
|
@ -188,18 +196,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
nof_retx = mexutils_getLength(INPUT);
|
||||
}
|
||||
|
||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT];
|
||||
for (int j=0;j<SRSLTE_MAX_RXANT;j++) {
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
ce[i][j] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
|
||||
if (!data_bytes) {
|
||||
return;
|
||||
}
|
||||
srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations);
|
||||
|
||||
input_fft = NULL;
|
||||
bool input_fft_allocated = false;
|
||||
int r=-1;
|
||||
for (int rvIdx=0;rvIdx<nof_retx && r != 0;rvIdx++) {
|
||||
|
||||
|
@ -218,11 +227,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexErrMsgTxt("Error reading input signal\n");
|
||||
return;
|
||||
}
|
||||
if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) {
|
||||
input_fft = input_signal;
|
||||
} else {
|
||||
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft);
|
||||
if (!(insignal_len % SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
for (int i=0;i<nof_antennas;i++) {
|
||||
input_fft[i] = &input_signal[i*insignal_len/nof_antennas];
|
||||
}
|
||||
} else if (!(insignal_len % SRSLTE_SF_LEN_PRB(cell.nof_prb))) {
|
||||
|
||||
for (int i=0;i<nof_antennas;i++) {
|
||||
input_fft[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
srslte_ofdm_rx_sf(&ofdm_rx, &input_signal[i*insignal_len/nof_antennas], input_fft[i]);
|
||||
input_fft_allocated = true;
|
||||
}
|
||||
free(input_signal);
|
||||
}
|
||||
|
||||
|
@ -230,16 +245,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
cf_t *cearray = NULL;
|
||||
mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
|
||||
cf_t *cearray_ptr = cearray;
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
ce[i][j] = *cearray_ptr;
|
||||
cearray_ptr++;
|
||||
for (int k=0;k<SRSLTE_MAX_RXANT;k++) {
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
ce[i][k][j] = *cearray_ptr;
|
||||
cearray_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cearray)
|
||||
free(cearray);
|
||||
} else {
|
||||
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
|
||||
srslte_chest_dl_estimate_multi(&chest, input_fft, ce, cfg.sf_idx, nof_antennas);
|
||||
}
|
||||
|
||||
float noise_power;
|
||||
|
@ -251,7 +268,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
||||
}
|
||||
|
||||
r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, rnti, data_bytes);
|
||||
r = srslte_pdsch_decode_multi(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, rnti, data_bytes);
|
||||
}
|
||||
|
||||
uint8_t *data = malloc(grant.mcs.tbs);
|
||||
|
@ -273,21 +290,41 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1);
|
||||
}
|
||||
if (nlhs >= 6) {
|
||||
mexutils_write_cf(ce[0], &plhs[5], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
|
||||
uint32_t len = nof_antennas*cell.nof_ports*SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
|
||||
cf_t *cearray_ptr = srslte_vec_malloc(len*sizeof(cf_t));
|
||||
int n=0;
|
||||
for (int k=0;k<nof_antennas;k++) {
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
cearray_ptr[n] = ce[i][k][j];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mexutils_write_cf(cearray_ptr, &plhs[5], len, 1);
|
||||
if (cearray_ptr) {
|
||||
free(cearray_ptr);
|
||||
}
|
||||
}
|
||||
srslte_softbuffer_rx_free(&softbuffer);
|
||||
srslte_chest_dl_free(&chest);
|
||||
srslte_pdsch_free(&pdsch);
|
||||
srslte_ofdm_rx_free(&ofdm_rx);
|
||||
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
free(ce[i]);
|
||||
for (int j=0;j<nof_antennas;j++) {
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
if (ce[i][j]) {
|
||||
free(ce[i][j]);
|
||||
}
|
||||
}
|
||||
if (input_fft_allocated) {
|
||||
if (input_fft[j]) {
|
||||
free(input_fft[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(data_bytes);
|
||||
free(data);
|
||||
if (input_fft) {
|
||||
free(input_fft);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue