Finished PDSCH MEX test. Read MCS from STDIN in pdsch_enodeb

master
ismagom 10 years ago
parent d993021880
commit 134eea27f8

@ -30,6 +30,7 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/select.h>
#include "liblte/phy/phy.h"
#include "liblte/rrc/rrc.h"
@ -179,13 +180,6 @@ void base_init() {
exit(-1);
}
/*
if (udpsource_set_nonblocking(&udp_source)) {
fprintf(stderr, "Error setting non-blocking\n");
exit(-1);
}
*/
if (udpsource_set_timeout(&udp_source, 5)) {
fprintf(stderr, "Error setting UDP socket timeout\n");
exit(-1);
@ -267,6 +261,60 @@ void base_free() {
}
int update_radl(ra_pdsch_t *ra_dl) {
ra_prb_t prb_alloc;
bzero(ra_dl, sizeof(ra_pdsch_t));
ra_dl->harq_process = 0;
ra_dl->mcs_idx = mcs_idx;
ra_dl->ndi = 0;
ra_dl->rv_idx = 0;
ra_dl->alloc_type = alloc_type0;
ra_dl->type0_alloc.rbg_bitmask = 0xffffffff;
ra_prb_get_dl(&prb_alloc, ra_dl, cell.nof_prb);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM);
ra_mcs_from_idx_dl(mcs_idx, cell.nof_prb, &ra_dl->mcs);
ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb);
if (pdsch_harq_setup(&harq_process, ra_dl->mcs, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return -1;
}
return 0;
}
/* Read new MCS from stdin */
int update_control(ra_pdsch_t *ra_dl) {
char input[128];
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
struct timeval to;
to.tv_sec = 0;
to.tv_usec = 0;
int n = select(1, &set, NULL, NULL, &to);
if (n == 1) {
// stdin ready
if (fgets(input, sizeof(input), stdin)) {
mcs_idx = atoi(input);
return update_radl(ra_dl);
}
return 0;
} else if (n < 0) {
// error
perror("select");
return -1;
} else {
return 0;
}
}
uint8_t data[10000], data_unpacked[10000];
int main(int argc, char **argv) {
@ -275,8 +323,7 @@ int main(int argc, char **argv) {
float sss_signal0[SSS_LEN]; // for subframe 0
float sss_signal5[SSS_LEN]; // for subframe 5
uint8_t bch_payload[BCH_PAYLOAD_LEN], bch_payload_packed[BCH_PAYLOAD_LEN/8];
ra_pdsch_t ra_dl;
ra_prb_t prb_alloc;
ra_pdsch_t ra_dl;
int i;
cf_t *sf_symbols[MAX_PORTS];
cf_t *slot1_symbols[MAX_PORTS];
@ -330,21 +377,9 @@ int main(int argc, char **argv) {
}
#endif
bzero(&ra_dl, sizeof(ra_pdsch_t));
ra_dl.harq_process = 0;
ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0;
ra_dl.rv_idx = 0;
ra_dl.alloc_type = alloc_type0;
ra_dl.type0_alloc.rbg_bitmask = 0xffffffff;
dci_msg_pack_pdsch(&ra_dl, &dci_msg, Format1, cell.nof_prb, false);
ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM);
ra_mcs_from_idx_dl(mcs_idx, cell.nof_prb, &ra_dl.mcs);
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
if (update_radl(&ra_dl)) {
exit(-1);
}
/* Initiate valid DCI locations */
for (i=0;i<NSUBFRAMES_X_FRAME;i++) {
@ -353,11 +388,6 @@ int main(int argc, char **argv) {
nf = 0;
if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
exit(-1);
}
bool send_data = false;
while (nf < nof_frames || nof_frames == -1) {
@ -380,6 +410,11 @@ int main(int argc, char **argv) {
pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
/* Update DL resource allocation from control port */
if (update_control(&ra_dl)) {
fprintf(stderr, "Error updating parameters from control port\n");
}
/* Transmit PDCCH + PDSCH only when there is data to send */
if (sf_idx != 0) {
if (udp_port > 0) {
@ -405,6 +440,7 @@ int main(int argc, char **argv) {
}
if (send_data) {
dci_msg_pack_pdsch(&ra_dl, &dci_msg, Format1, cell.nof_prb, false);
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
if (pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], 1234, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
@ -433,7 +469,7 @@ int main(int argc, char **argv) {
nf++;
}
sfn = (sfn + 1) % 1024;
printf("SFN: %4d\r", sfn);
printf("SFN: %4d\tType new MCS index and press Enter\r", sfn);
fflush(stdout);
}

@ -675,60 +675,66 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
harq_process != NULL)
{
nof_bits = harq_process->mcs.tbs;
nof_symbols = harq_process->prb_alloc.re_sf[subframe];
nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod);
if (q->rnti_is_set) {
nof_bits = harq_process->mcs.tbs;
nof_symbols = harq_process->prb_alloc.re_sf[subframe];
nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod);
INFO("Decoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
subframe, lte_mod_string(harq_process->mcs.mod), nof_bits, nof_symbols, nof_bits_e, rv_idx);
INFO("Decoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
subframe, lte_mod_string(harq_process->mcs.mod), nof_bits, nof_symbols, nof_bits_e, rv_idx);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pdsch_x[i];
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq_process->prb_alloc, subframe);
if (n != nof_symbols) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
return LIBLTE_ERROR;
}
/* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) {
n = pdsch_get(q, ce[i], q->ce[i], &harq_process->prb_alloc, subframe);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pdsch_x[i];
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq_process->prb_alloc, subframe);
if (n != nof_symbols) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
return LIBLTE_ERROR;
}
}
/* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) {
n = pdsch_get(q, ce[i], q->ce[i], &harq_process->prb_alloc, subframe);
if (n != nof_symbols) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
return LIBLTE_ERROR;
}
}
/* TODO: only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d,
nof_symbols, noise_estimate);
/* TODO: only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d,
nof_symbols, noise_estimate);
} else {
predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports,
nof_symbols, noise_estimate);
layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports,
nof_symbols / q->cell.nof_ports);
}
/* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
demod_soft_sigma_set(&q->demod, sqrt((float) lte_mod_bits_x_symbol(harq_process->mcs.mod)/2));
demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols);
/* descramble */
scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, nof_bits_e);
return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, harq_process, rv_idx);
} else {
predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports,
nof_symbols, noise_estimate);
layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports,
nof_symbols / q->cell.nof_ports);
fprintf(stderr, "Must call pdsch_set_rnti() before calling pdsch_decode()\n");
return LIBLTE_ERROR;
}
/* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
demod_soft_sigma_set(&q->demod, sqrt((float) lte_mod_bits_x_symbol(harq_process->mcs.mod)/2));
demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols);
/* descramble */
scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, nof_bits_e);
return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, harq_process, rv_idx);
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}

@ -98,6 +98,8 @@ ADD_TEST(pdsch_test_qpsk pdsch_test -l 1000 -m 2 -n 50 -r 1)
ADD_TEST(pdsch_test_qam16 pdsch_test -l 50000 -m 4 -n 110)
ADD_TEST(pdsch_test_qam64 pdsch_test -l 5000 -m 6 -n 50 -r 0)
BuildMex(MEXNAME pdsch SOURCES pdsch_test_mex.c LIBRARIES lte_phy liblte_mex)
########################################################################
# FILE TEST
########################################################################

@ -137,13 +137,14 @@ int main(int argc, char **argv) {
mcs.tbs = tbs;
mcs.mod = modulation;
prb_alloc.slot[0].nof_prb = cell.nof_prb;
for (i=0;i<prb_alloc.slot[0].nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = i;
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, 2, CPNORM);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, CPNORM);
/* init memory */
for (i=0;i<cell.nof_ports;i++) {

@ -32,16 +32,16 @@
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define ENBCFG prhs[0]
#define RNTI prhs[1]
#define TBS prhs[2]
#define INPUT prhs[3]
#define ENBCFG prhs[0]
#define PDSCHCFG prhs[1]
#define TBS prhs[2]
#define INPUT prhs[3]
#define NOF_INPUTS 4
void help()
{
mexErrMsgTxt
("[decoded_ok, llr, rm, bits, symbols] = liblte_pdsch(enbConfig, RNTI, rxWaveform)\n\n");
("[decoded_ok, llr, rm, bits, symbols] = liblte_pdsch(enbConfig, pdschConfig, trblklen, rxWaveform)\n\n");
}
/* the gateway function */
@ -53,13 +53,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
chest_dl_t chest;
lte_fft_t fft;
uint32_t cfi, sf_idx;
uint16_t rnti;
cf_t *input_fft, *input_signal;
int nof_re;
ra_mcs_t mcs;
ra_prb_t prb_alloc;
pdsch_harq_t harq_process;
uint32_t rv;
uint32_t rnti32;
if (nrhs != NOF_INPUTS) {
help();
@ -71,6 +71,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
if (mexutils_read_uint32_struct(PDSCHCFG, "RNTI", &rnti32)) {
mexErrMsgTxt("Field RNTI not found in pdsch config\n");
return;
}
if (mexutils_read_uint32_struct(ENBCFG, "CFI", &cfi)) {
help();
return;
@ -80,35 +85,80 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
if (pdsch_init(&pdsch, cell)) {
mexErrMsgTxt("Error initiating PDSCH\n");
return;
}
pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff));
if (pdsch_harq_init(&harq_process, &pdsch)) {
mexErrMsgTxt("Error initiating HARQ process\n");
return;
}
if (chest_dl_init(&chest, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
mexErrMsgTxt("Error initializing equalizer\n");
return;
}
if (lte_fft_init(&fft, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n");
mexErrMsgTxt("Error initializing FFT\n");
return;
}
rnti = (uint16_t) mxGetScalar(RNTI);
nof_re = 2 * CPNORM_NSYMB * cell.nof_prb * RE_X_RB;
mcs.tbs = mxGetScalar(TBS);
mcs.mod = modulation;
if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) {
help();
if (mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n");
return;
}
if (mexutils_read_uint32_struct(PDSCHCFG, "RV", &rv)) {
mexErrMsgTxt("Field RV not found in pdsch config\n");
return;
}
prb_alloc.slot[0].nof_prb = cell.nof_prb;
for (i=0;i<prb_alloc.slot[0].nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = i;
char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
mcs.mod = LTE_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = LTE_QAM16;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = LTE_QAM64;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
}
mxFree(mod_str);
float *prbset;
mxArray *p;
p = mxGetField(PDSCHCFG, 0, "PRBSet");
if (!p) {
mexErrMsgTxt("Error field PRBSet not found\n");
return;
}
// Only localized PRB supported
prb_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset);
for (i=0;i<cell.nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = false;
for (int j=0;j<prb_alloc.slot[0].nof_prb && !prb_alloc.slot[0].prb_idx[i];j++) {
if ((int) prbset[j] == i) {
prb_alloc.slot[0].prb_idx[i] = true;
}
}
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, 2, CPNORM);
free(prbset);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
/** Allocate input buffers */
if (mexutils_read_cf(INPUT, &input_signal) < 0) {
@ -143,51 +193,42 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} else {
noise_power = chest_dl_get_noise_estimate(&chest);
}
pdcch_extract_llr(&pdcch, input_fft, ce, noise_power, sf_idx, cfi);
uint32_t nof_locations;
if (rnti == SIRNTI) {
nof_locations = pdcch_common_locations(&pdcch, locations, MAX_CANDIDATES, cfi);
formats = common_formats;
nof_formats = nof_common_formats;
} else {
nof_locations = pdcch_ue_locations(&pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
formats = ue_formats;
nof_formats = nof_ue_formats;
}
uint16_t crc_rem=0;
dci_msg_t dci_msg;
bzero(&dci_msg, sizeof(dci_msg_t));
for (int f=0;f<nof_formats;f++) {
for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_decode_msg(&pdcch, &dci_msg, &locations[i], formats[f], &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return;
}
}
}
if (pdsch_harq_setup(&harq_process, mcs, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
uint8_t *data = malloc(sizeof(uint8_t) * mcs.tbs);
if (!data) {
return;
}
int r = pdsch_decode(&pdsch, input_fft, ce, noise_power, data, sf_idx, &harq_process, rv);
tbs_is_zero:
if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(crc_rem == rnti);
plhs[0] = mxCreateLogicalScalar(r == 0);
}
int nof_bits = (regs_pdcch_nregs(&regs, cfi) / 9) * 72;
if (nlhs >= 2) {
mexutils_write_f(pdcch.pdcch_llr, &plhs[1], nof_bits, 1);
mexutils_write_uint8(data, &plhs[1], mcs.tbs, 1);
}
if (nlhs >= 3) {
mexutils_write_cf(pdcch.pdcch_symbols[0], &plhs[2], 36*pdcch.nof_cce, 1);
mexutils_write_cf(pdsch.pdsch_symbols[0], &plhs[2], harq_process.prb_alloc.re_sf[sf_idx], 1);
}
if (nlhs >= 4) {
mexutils_write_cf(pdsch.pdsch_d, &plhs[3], harq_process.prb_alloc.re_sf[sf_idx], 1);
}
chest_dl_free(&chest);
lte_fft_free(&fft);
pdcch_free(&pdcch);
regs_free(&regs);
pdsch_free(&pdsch);
for (i=0;i<cell.nof_ports;i++) {
free(ce[i]);
}
free(data);
free(input_signal);
free(input_fft);

@ -4,11 +4,11 @@
% A structure |enbConfig| is used to configure the eNodeB.
clear
Npackets = 25;
SNR_values = linspace(1,6,4);
Npackets = 10;
SNR_values = linspace(2,6,4);
%% Choose RMC
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.12',[1;0;0;1]);
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.11',[1;0;0;1]);
waveform = sum(waveform,2);
Nsf = 8;
@ -16,7 +16,7 @@ Nsf = 8;
%% Setup Fading channel model
cfg.Seed = 8; % Random channel seed
cfg.NRxAnts = 1; % 1 receive antenna
cfg.DelayProfile = 'EPA'; % EVA delay spread
cfg.DelayProfile = 'EVA'; % EVA delay spread
cfg.DopplerFreq = 5; % 120Hz Doppler frequency
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
cfg.InitTime = 0; % Initialize at time zero
@ -57,7 +57,8 @@ for snr_idx=1:length(SNR_values)
frame_rx = lteOFDMDemodulate(rmccFgOut, rxWaveform);
for sf_idx=0:Nsf
flen=length(rxWaveform)/10;
subframe_waveform = rxWaveform(sf_idx*flen+1:(sf_idx+1)*flen);
subframe_rx=frame_rx(:,sf_idx*14+1:(sf_idx+1)*14);
rmccFgOut.NSubframe=sf_idx;
rmccFgOut.TotSubframes=1;
@ -73,8 +74,14 @@ for snr_idx=1:length(SNR_values)
%% Same with libLTE
%[found_liblte, llr, pdcchSymbols2] = liblte_pdsch(rmccFgOut, ueConfig.RNTI, rxWaveform);
%decoded_liblte(snr_idx) = decoded_liblte(snr_idx)+found_liblte;
if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0)
[dec2, llr, pdschRx, pdschSymbols2] = liblte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ...
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ...
subframe_waveform);
else
dec2 = 1;
end
decoded_liblte(snr_idx) = decoded_liblte(snr_idx)+dec2;
end
end
fprintf('SNR: %.1f\n',SNRdB)

@ -47,6 +47,9 @@ LIBLTE_API bool mexutils_isScalar(const mxArray *ptr);
LIBLTE_API int mexutils_read_cell(const mxArray *ptr,
lte_cell_t *cell);
LIBLTE_API char *mexutils_get_char_struct(const mxArray *ptr,
const char *field_name);
LIBLTE_API int mexutils_read_uint32_struct(const mxArray *ptr,
const char *field_name,
uint32_t *value);

@ -36,6 +36,21 @@ bool mexutils_isScalar(const mxArray *ptr) {
return mxGetM(ptr) == 1 && mxGetN(ptr) == 1;
}
char *mexutils_get_char_struct(const mxArray *ptr, const char *field_name) {
mxArray *p;
p = mxGetField(ptr, 0, field_name);
if (!p) {
mexPrintf("Error field %s not found\n", field_name);
return NULL;
}
if (mxIsCell(p)) {
return mxArrayToString(mxGetCell(p,0));
} else {
return mxArrayToString(p);
}
}
int mexutils_read_uint32_struct(const mxArray *ptr, const char *field_name, uint32_t *value)
{
mxArray *p;

Loading…
Cancel
Save