diff --git a/matlab/tests/pdsch_decode_test.m b/matlab/tests/pdsch_decode_test.m new file mode 100644 index 000000000..4d542bbd1 --- /dev/null +++ b/matlab/tests/pdsch_decode_test.m @@ -0,0 +1,63 @@ +enb=struct('NCellID',16,'NDLRB',6,'NSubframe',5,'CFI',3,'CyclicPrefix','Normal','CellRefP',1,'Ng','One','PHICHDuration','Normal','DuplexMode','FDD'); + +RNTI=65535; + +addpath('../../build/srslte/lib/phch/test') + +cec.PilotAverage = 'UserDefined'; % Type of pilot averaging +cec.FreqWindow = 9; % Frequency window size +cec.TimeWindow = 9; % Time window size +cec.InterpType = 'cubic'; % 2D interpolation type +cec.InterpWindow = 'Centered'; % Interpolation window type +cec.InterpWinSize = 1; % Interpolation window size + +subframe_rx=lteOFDMDemodulate(enb,inputSignal); +[hest,nest] = lteDLChannelEstimate(enb, cec, subframe_rx); + +% Search PDCCH +pdcchIndices = ltePDCCHIndices(enb); +[pdcchRx, pdcchHest] = lteExtractResources(pdcchIndices, subframe_rx, hest); +[dciBits, pdcchSymbols] = ltePDCCHDecode(enb, pdcchRx, pdcchHest, nest); +pdcch = struct('RNTI', RNTI); +dci = ltePDCCHSearch(enb, pdcch, dciBits); % Search PDCCH for DCI + +if ~isempty(dci) + + dci = dci{1}; + disp(dci); + + % Get the PDSCH configuration from the DCI + [pdsch, trblklen] = hPDSCHConfiguration(enb, dci, pdcch.RNTI); + pdsch.NTurboDecIts = 5; + fprintf('PDSCH settings after DCI decoding:\n'); + disp(pdsch); + + fprintf('Decoding PDSCH...\n\n'); + % Get PDSCH indices + [pdschIndices,pdschIndicesInfo] = ltePDSCHIndices(enb, pdsch, pdsch.PRBSet); + [pdschRx, pdschHest] = lteExtractResources(pdschIndices, subframe_rx, hest); + % Decode PDSCH + [dlschBits,pdschSymbols] = ltePDSCHDecode(enb, pdsch, pdschRx, pdschHest, nest); + [sib1, crc] = lteDLSCHDecode(enb, pdsch, trblklen, dlschBits); + + [dec2, data, pdschRx2, pdschSymbols2, e_bits, indices] = srslte_pdsch(enb, pdsch, ... + trblklen, ... + subframe_rx); + + + scatter(real(pdschSymbols{1}),imag(pdschSymbols{1})) + + if crc == 0 + fprintf('PDSCH OK.\n\n'); + else + fprintf('PDSCH ERROR.\n\n'); + end + + else + % indicate that DCI decoding failed + fprintf('DCI decoding failed.\n\n'); +end + +indices=indices+1; +plot(t,indices(t),t,pdschIndices(t)) + \ No newline at end of file diff --git a/mex/include/srslte/mex/mexutils.h b/mex/include/srslte/mex/mexutils.h index 485fa0d26..ea9115bb9 100644 --- a/mex/include/srslte/mex/mexutils.h +++ b/mex/include/srslte/mex/mexutils.h @@ -85,6 +85,9 @@ SRSLTE_API int mexutils_write_int(int *buffer, SRSLTE_API int mexutils_read_uint8(const mxArray *ptr, uint8_t **buffer); +SRSLTE_API int mexutils_read_uint64(const mxArray *ptr, + uint64_t **buffer); + SRSLTE_API int mexutils_read_f(const mxArray *ptr, float **buffer); diff --git a/mex/lib/mexutils.c b/mex/lib/mexutils.c index 6be84da2f..bdb87d70f 100644 --- a/mex/lib/mexutils.c +++ b/mex/lib/mexutils.c @@ -137,6 +137,22 @@ int mexutils_read_uint8(const mxArray *ptr, uint8_t **buffer) { } } + +int mexutils_read_uint64(const mxArray *ptr, uint64_t **buffer) { + int numelems = mxGetNumberOfElements(ptr); + uint64_t *tmp = srslte_vec_malloc(numelems * sizeof(uint64_t)); + if (tmp) { + uint64_t *inr=mxGetPr(ptr); + for (int i=0;ifile_nof_prb = 25; args->file_nof_ports = 1; args->file_cell_id = 0; - args->file_offset = 0; + args->file_offset_time = 0; + args->file_offset_freq = 0; args->uhd_args = ""; args->uhd_freq = -1.0; - args->uhd_freq_offset = 0.0; args->uhd_gain = -1.0; args->net_port = -1; args->net_address = "127.0.0.1"; @@ -117,16 +117,16 @@ void args_default(prog_args_t *args) { } void usage(prog_args_t *args, char *prog) { - printf("Usage: %s [agpPOcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog); + printf("Usage: %s [agpPoOcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog); #ifndef DISABLE_UHD printf("\t-a UHD args [Default %s]\n", args->uhd_args); printf("\t-g UHD fix RX gain [Default AGC]\n"); - printf("\t-o UHD RX freq offset [Default %.1f MHz]\n", args->uhd_freq_offset/1000000); #else printf("\t UHD is disabled. CUHD library not available\n"); #endif printf("\t-i input_file [Default USRP]\n"); - printf("\t-O offset samples for input file [Default %d]\n", args->file_offset); + printf("\t-o offset frequency correction (in Hz) for input file [Default %.1f Hz]\n", args->file_offset_freq); + printf("\t-O offset samples for input file [Default %d]\n", args->file_offset_time); printf("\t-p nof_prb for input file [Default %d]\n", args->file_nof_prb); printf("\t-P nof_ports for input file [Default %d]\n", args->file_nof_ports); printf("\t-c cell_id for input file [Default %d]\n", args->file_cell_id); @@ -162,8 +162,11 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 'P': args->file_nof_ports = atoi(argv[optind]); break; + case 'o': + args->file_offset_freq = atof(argv[optind]); + break; case 'O': - args->file_offset = atoi(argv[optind]); + args->file_offset_time = atoi(argv[optind]); break; case 'c': args->file_cell_id = atoi(argv[optind]); @@ -180,9 +183,6 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 't': args->time_offset = atoi(argv[optind]); break; - case 'o': - args->uhd_freq_offset = atof(argv[optind]); - break; case 'f': args->uhd_freq = atof(argv[optind]); break; @@ -320,7 +320,7 @@ int main(int argc, char **argv) { cuhd_set_master_clock_rate(uhd, 30.72e6); /* set receiver frequency */ - cuhd_set_rx_freq_offset(uhd, (double) prog_args.uhd_freq, prog_args.uhd_freq_offset); + cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq); cuhd_rx_wait_lo_locked(uhd); printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000); @@ -373,7 +373,8 @@ int main(int argc, char **argv) { cell.nof_ports = prog_args.file_nof_ports; cell.nof_prb = prog_args.file_nof_prb; - if (srslte_ue_sync_init_file(&ue_sync, prog_args.file_nof_prb, prog_args.input_file_name, prog_args.file_offset)) { + if (srslte_ue_sync_init_file(&ue_sync, prog_args.file_nof_prb, + prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq)) { fprintf(stderr, "Error initiating ue_sync\n"); exit(-1); } @@ -485,7 +486,7 @@ int main(int argc, char **argv) { uint32_t rv = ((uint32_t) ceilf((float)1.5*k))%4; n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data, srslte_ue_sync_get_sfidx(&ue_sync), - SRSLTE_SIRNTI, rv); + SRSLTE_SIRNTI, rv); } if (n < 0) { // fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); diff --git a/srslte/include/srslte/ue/ue_sync.h b/srslte/include/srslte/ue/ue_sync.h index 4eea06d8e..e81c348d2 100644 --- a/srslte/include/srslte/ue/ue_sync.h +++ b/srslte/include/srslte/ue/ue_sync.h @@ -80,6 +80,8 @@ typedef struct SRSLTE_API { srslte_filesource_t file_source; bool file_mode; + float file_cfo; + srslte_cfo_t file_cfo_correct; srslte_ue_sync_state_t state; @@ -124,7 +126,8 @@ SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, - int offset); + int offset_time, + float offset_freq); SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q); diff --git a/srslte/lib/phch/src/pdsch.c b/srslte/lib/phch/src/pdsch.c index 4117d6736..06d2b6ea3 100644 --- a/srslte/lib/phch/src/pdsch.c +++ b/srslte/lib/phch/src/pdsch.c @@ -121,8 +121,12 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_g // This is a symbol in a normal PRB with or without references if (l >= lstart && l < lend) { if (SRSLTE_SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) { - if (nof_refs == 2 && l != 0) { - offset = q->cell.id % 3 + 3; + if (nof_refs == 2) { + if (l == 0) { + offset = q->cell.id % 6; + } else { + offset = (q->cell.id + 3) % 6; + } } else { offset = q->cell.id % 3; } @@ -411,6 +415,11 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, cfg->nbits.nof_re / q->cell.nof_ports); } + if (SRSLTE_VERBOSE_ISDEBUG()) { + DEBUG("pdsch_symbols: ",0); + srslte_vec_fprint_c(stdout, q->d, cfg->nbits.nof_re); + } + /* 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 diff --git a/srslte/lib/phch/src/sch.c b/srslte/lib/phch/src/sch.c index 961bd6551..9fbee2a2a 100644 --- a/srslte/lib/phch/src/sch.c +++ b/srslte/lib/phch/src/sch.c @@ -406,11 +406,6 @@ static int decode_tb(srslte_sch_t *q, return SRSLTE_ERROR; } - if (SRSLTE_VERBOSE_ISDEBUG()) { - DEBUG("CB#%d RMOUT: ", i); - srslte_vec_fprint_s(stdout, softbuffer->buffer_f[i], 3*cb_len+12); - } - /* Turbo Decoding with CRC-based early stopping */ q->nof_iterations = 0; uint32_t len_crc; diff --git a/srslte/lib/phch/test/pdsch_test_mex.c b/srslte/lib/phch/test/pdsch_test_mex.c index b943cf25c..a73309d63 100644 --- a/srslte/lib/phch/test/pdsch_test_mex.c +++ b/srslte/lib/phch/test/pdsch_test_mex.c @@ -136,7 +136,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mxFree(mod_str); - float *prbset; mxArray *p; p = mxGetField(PDSCHCFG, 0, "PRBSet"); if (!p) { @@ -144,9 +143,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - // Only localized PRB supported - grant.nof_prb = mexutils_read_f(p, &prbset); - + float *prbset_f; + uint64_t *prbset; + if (mxGetClassID(p) == mxDOUBLE_CLASS) { + grant.nof_prb = mexutils_read_f(p, &prbset_f); + prbset = malloc(sizeof(uint64_t)*grant.nof_prb); + for (i=0;i= 6) { - mexutils_write_s(softbuffer.buffer_f[9], &plhs[5], 16908, 1); + mexutils_write_int(indices, &plhs[5], cfg.nbits.nof_re, 1); } srslte_chest_dl_free(&chest); diff --git a/srslte/lib/sync/test/pss_file.c b/srslte/lib/sync/test/pss_file.c index 90524c619..afca92f5c 100644 --- a/srslte/lib/sync/test/pss_file.c +++ b/srslte/lib/sync/test/pss_file.c @@ -243,7 +243,7 @@ int main(int argc, char **argv) { if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { sss_error2++; } - printf("sf_idx = %d\n", srslte_sss_synch_subframe(m0, m1)); + INFO("sf_idx = %d\n", srslte_sss_synch_subframe(m0, m1)); INFO("Partial N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); srslte_sss_synch_m0m1_diff(&sss, &buffer[sss_idx], &m0, &m0_value, &m1, &m1_value); if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { @@ -295,7 +295,7 @@ int main(int argc, char **argv) { printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r", frame_cnt, - peak_idx, + peak_idx - flen/10, peak_value, mean_peak, (float) nof_det/frame_cnt, (float) nof_nopeakdet/frame_cnt, mean_cfo*15, diff --git a/srslte/lib/ue/src/ue_sync.c b/srslte/lib/ue/src/ue_sync.c index c3c13ec7a..9620cdc91 100644 --- a/srslte/lib/ue/src/ue_sync.c +++ b/srslte/lib/ue/src/ue_sync.c @@ -47,7 +47,7 @@ cf_t dummy[MAX_TIME_OFFSET]; cf_t kk[1024*1024]; -int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset) { +int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time, float offset_freq) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && @@ -58,6 +58,14 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n bzero(q, sizeof(srslte_ue_sync_t)); q->file_mode = true; q->sf_len = SRSLTE_SF_LEN(srslte_symbol_sz(nof_prb)); + q->file_cfo = -offset_freq; + q->correct_cfo = true; + q->fft_size = srslte_symbol_sz(nof_prb); + + if (srslte_cfo_init(&q->file_cfo_correct, 2*q->sf_len)) { + fprintf(stderr, "Error initiating CFO\n"); + goto clean_exit; + } if (srslte_filesource_init(&q->file_source, file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { fprintf(stderr, "Error opening file %s\n", file_name); @@ -70,9 +78,9 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n goto clean_exit; } - INFO("Offseting input file by %d samples\n", offset); + INFO("Offseting input file by %d samples and %.1f KHz\n", offset_time, offset_freq/1000); - srslte_filesource_read(&q->file_source, kk, offset); + srslte_filesource_read(&q->file_source, kk, offset_time); srslte_ue_sync_reset(q); ret = SRSLTE_SUCCESS; @@ -421,6 +429,13 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { return SRSLTE_ERROR; } } + if (q->correct_cfo) { + srslte_cfo_correct(&q->file_cfo_correct, + input_buffer, + input_buffer, + q->file_cfo / 15000 / q->fft_size); + + } q->sf_idx++; if (q->sf_idx == 10) { q->sf_idx = 0;