From 9d7d6c94150aef6aca7d95e886d949caf3a7ee95 Mon Sep 17 00:00:00 2001 From: yagoda Date: Tue, 15 May 2018 16:13:03 +0200 Subject: [PATCH] adding adaptations to the phy layer for mbms --- lib/examples/pdsch_enodeb.c | 66 +++++++++----- lib/examples/pdsch_ue.c | 17 +++- .../srslte/phy/ch_estimation/refsignal_dl.h | 6 +- lib/include/srslte/phy/dft/ofdm.h | 2 +- lib/include/srslte/phy/enb/enb_dl.h | 20 ++++- lib/include/srslte/phy/phch/pmch.h | 2 +- lib/src/phy/ch_estimation/chest_dl.c | 30 +++++-- lib/src/phy/ch_estimation/refsignal_dl.c | 32 +++++-- lib/src/phy/dft/ofdm.c | 12 +-- lib/src/phy/enb/enb_dl.c | 87 +++++++++++++++++-- lib/src/phy/phch/pmch.c | 19 +++- lib/src/phy/ue/ue_dl.c | 20 ++++- 12 files changed, 248 insertions(+), 65 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 158d672ea..a75deded6 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -123,7 +123,7 @@ int prbset_orig = 0; #define DATA_BUFF_SZ 1024*1024 -uint8_t *data[2], data2[DATA_BUFF_SZ]; +uint8_t *data_mbms, *data[2], data2[DATA_BUFF_SZ]; uint8_t data_tmp[DATA_BUFF_SZ]; void usage(char *prog) { @@ -145,7 +145,7 @@ void usage(char *prog) { printf("\t-x Transmission mode[single|diversity|cdd|multiplex] [Default %s]\n", mimo_type_str); printf("\t-b Precoding Matrix Index (multiplex mode only)* [Default %d]\n", multiplex_pmi); printf("\t-w Number of codewords/layers (multiplex mode only)* [Default %d]\n", multiplex_nof_layers); - printf("\t-u listen TCP port for input data (-1 is random) [Default %d]\n", net_port); + printf("\t-u listen TCP/UDP port for input data (if mbsfn is active then the stream is over mbsfn only) (-1 is random) [Default %d]\n", net_port); printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-s output file SNR [Default %f]\n", output_file_snr); printf("\n"); @@ -256,6 +256,7 @@ void base_init() { } bzero(data[i], sizeof(uint8_t) * SOFTBUFFER_SIZE); } + data_mbms = srslte_vec_malloc(sizeof(uint8_t) * SOFTBUFFER_SIZE); /* init memory */ for (i = 0; i < SRSLTE_MAX_PORTS; i++) { @@ -659,15 +660,21 @@ void *net_thread_fnc(void *arg) { n = srslte_netsource_read(&net_source, &data2[rpm], DATA_BUFF_SZ-rpm); if (n > 0) { // FIXME: I assume that both transport blocks have same size in case of 2 tb are active - int nbytes = 1 + (pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs - 1) / 8; + + int nbytes = 1 + (((mbsfn_area_id > -1)?(pmch_cfg.grant.mcs[0].tbs):(pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs)) - 1) / 8; rpm += n; INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); wpm = 0; while (rpm >= nbytes) { // wait for packet to be transmitted sem_wait(&net_sem); - memcpy(data[0], &data2[wpm], nbytes / (size_t) 2); - memcpy(data[1], &data2[wpm], nbytes / (size_t) 2); + if(mbsfn_area_id > -1){ + memcpy(data_mbms, &data2[wpm], nbytes); + } + else{ + memcpy(data[0], &data2[wpm], nbytes / (size_t) 2); + memcpy(data[1], &data2[wpm], nbytes / (size_t) 2); + } INFO("Sent %d/%d bytes ready\n", nbytes, rpm); rpm -= nbytes; wpm += nbytes; @@ -739,10 +746,15 @@ int main(int argc, char **argv) { exit(-1); } if(mbsfn_area_id > -1) { - if(srslte_refsignal_mbsfn_init(&mbsfn_refs, cell, mbsfn_area_id)) { + if(srslte_refsignal_mbsfn_init(&mbsfn_refs, cell.nof_prb)) { fprintf(stderr, "Error initializing equalizer\n"); exit(-1); } + if (srslte_refsignal_mbsfn_set_cell(&mbsfn_refs, cell, mbsfn_area_id)) { + fprintf(stderr, "Error initializing MBSFNR signal\n"); + exit(-1); + } + } if(srslte_refsignal_cs_set_cell(&csr_refs, cell)){ @@ -801,7 +813,7 @@ int main(int argc, char **argv) { exit(-1); } } - + pmch_cfg.grant.mcs[0].tbs = 1096; /* Initiate valid DCI locations */ for (i=0;i -1){ + if(sf_idx == 2 && mbsfn_area_id > -1){ srslte_refsignal_mbsfn_put_sf(cell, 0,csr_refs.pilots[0][sf_idx], mbsfn_refs.pilots[0][sf_idx], sf_symbols[0]); } else { for (i = 0; i < cell.nof_ports; i++) { @@ -932,41 +944,46 @@ int main(int argc, char **argv) { } } } - net_packet_ready = false; - sem_post(&net_sem); + if(mbsfn_area_id < 0){ + net_packet_ready = false; + sem_post(&net_sem); + } } }else{ // We're sending MCH on subframe 1 - PDCCH + PMCH /* Encode PDCCH */ - INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L); - srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, cell.nof_ports, false); - if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], M_CRNTI, sf_symbols, sf_idx, cfi)) { - fprintf(stderr, "Error encoding DCI message\n"); - exit(-1); - } + //INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L); + //srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, cell.nof_ports, false); + //if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], M_CRNTI, sf_symbols, sf_idx, cfi)) { + // fprintf(stderr, "Error encoding DCI message\n"); + // exit(-1); + // } /* Configure pmch_cfg parameters */ srslte_ra_dl_grant_t grant; grant.tb_en[0] = true; grant.tb_en[1] = false; - grant.mcs[0].idx = 2; - grant.mcs[0].mod = SRSLTE_MOD_QPSK; + + grant.mcs[0].idx = 13; grant.nof_prb = cell.nof_prb; grant.sf_type = SRSLTE_SF_MBSFN; - grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb); + grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); for(int i = 0; i < 2; i++){ for(int j = 0; j < grant.nof_prb; j++){ grant.prb_idx[i][j] = true; } } + for(int i = 0; i < grant.mcs[0].tbs/8;i++) + { + data_mbms[i] = i%255; + } - if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, sf_idx)) { fprintf(stderr, "Error configuring PMCH\n"); exit(-1); - } + } /* Encode PMCH */ - if (srslte_pmch_encode(&pmch, &pmch_cfg, softbuffers[0], data[0], mbsfn_area_id, sf_symbols)) { + if (srslte_pmch_encode(&pmch, &pmch_cfg, softbuffers[0], data_mbms, mbsfn_area_id, sf_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); exit(-1); } @@ -984,13 +1001,14 @@ int main(int argc, char **argv) { } /* Transform to OFDM symbols */ - if(sf_idx != 1 || mbsfn_area_id < 0){ + if(sf_idx != 2 || mbsfn_area_id < 0){ for (i = 0; i < cell.nof_ports; i++) { srslte_ofdm_tx_sf(&ifft[i]); } }else{ srslte_ofdm_tx_sf(&ifft_mbsfn); } + /* send to file or usrp */ if (output_file_name) { diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index fc99fdc9a..c4334cd66 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -864,6 +864,8 @@ int main(int argc, char **argv) { PRINT_LINE_ADVANCE_CURSOR(); ue_dl.pdsch_pkt_errors = 0; ue_dl.pdsch_pkts_total = 0; + ue_dl.pmch_pkt_errors = 0; + ue_dl.pmch_pkts_total = 0; /* ue_dl.pkt_errors = 0; ue_dl.pkts_total = 0; @@ -944,7 +946,7 @@ int main(int argc, char **argv) { plot_real_t p_sync, pce; -plot_scatter_t pscatequal, pscatequal_pdcch; +plot_scatter_t pscatequal, pscatequal_pdcch, pscatequal_pmch; float tmp_plot[110*15*2048]; float tmp_plot2[110*15*2048]; @@ -963,6 +965,15 @@ void *plot_thread_run(void *arg) { plot_scatter_setYAxisScale(&pscatequal, -4, 4); plot_scatter_addToWindowGrid(&pscatequal, (char*)"pdsch_ue", 0, 0); + + + + plot_scatter_init(&pscatequal_pmch); + plot_scatter_setTitle(&pscatequal_pmch, "PMCH - Equalized Symbols"); + plot_scatter_setXAxisScale(&pscatequal_pmch, -4, 4); + plot_scatter_setYAxisScale(&pscatequal_pmch, -4, 4); + + plot_scatter_addToWindowGrid(&pscatequal_pmch, (char*)"pdsch_ue", 0, 1); if (!prog_args.disable_plots_except_constellation) { plot_real_init(&pce); @@ -979,7 +990,7 @@ void *plot_thread_run(void *arg) { plot_scatter_setXAxisScale(&pscatequal_pdcch, -4, 4); plot_scatter_setYAxisScale(&pscatequal_pdcch, -4, 4); - plot_real_addToWindowGrid(&pce, (char*)"pdsch_ue", 0, 1); + plot_real_addToWindowGrid(&pce, (char*)"pdsch_ue", 0, 2); plot_real_addToWindowGrid(&pscatequal_pdcch, (char*)"pdsch_ue", 1, 0); plot_real_addToWindowGrid(&p_sync, (char*)"pdsch_ue", 1, 1); } @@ -988,6 +999,7 @@ void *plot_thread_run(void *arg) { sem_wait(&plot_sem); uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits[0].nof_re; + uint32_t nof_symbols_pmch = ue_dl.pmch_cfg.nbits[0].nof_re; if (!prog_args.disable_plots_except_constellation) { for (i = 0; i < nof_re; i++) { tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); @@ -1031,6 +1043,7 @@ void *plot_thread_run(void *arg) { plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols); + plot_scatter_setNewData(&pscatequal_pmch, ue_dl.pmch.d, nof_symbols_pmch); if (plot_sf_idx == 1) { if (prog_args.net_port_signal > 0) { srslte_netsink_write(&net_sink_signal, &sf_buffer[srslte_ue_sync_sf_len(&ue_sync)/7], diff --git a/lib/include/srslte/phy/ch_estimation/refsignal_dl.h b/lib/include/srslte/phy/ch_estimation/refsignal_dl.h index 6167d8d4e..06809186e 100644 --- a/lib/include/srslte/phy/ch_estimation/refsignal_dl.h +++ b/lib/include/srslte/phy/ch_estimation/refsignal_dl.h @@ -93,8 +93,10 @@ SRSLTE_API uint32_t srslte_refsignal_cs_v(uint32_t port_id, SRSLTE_API uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id); -SRSLTE_API int srslte_refsignal_mbsfn_init(srslte_refsignal_t *q, srslte_cell_t cell, - uint16_t mbsfn_area_id); +SRSLTE_API int srslte_refsignal_mbsfn_init(srslte_refsignal_t *q, uint32_t max_prb); + +SRSLTE_API int srslte_refsignal_mbsfn_set_cell(srslte_refsignal_t * q, + srslte_cell_t cell, uint16_t mbsfn_area_id); SRSLTE_API int srslte_refsignal_mbsfn_get_sf(srslte_cell_t cell, uint32_t port_id, diff --git a/lib/include/srslte/phy/dft/ofdm.h b/lib/include/srslte/phy/dft/ofdm.h index 6f31ed3ab..c28d41bdd 100644 --- a/lib/include/srslte/phy/dft/ofdm.h +++ b/lib/include/srslte/phy/dft/ofdm.h @@ -92,7 +92,7 @@ SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp_type, cf_t *in_buffer, cf_t *out_buffer, - uint32_t nof_prb); + uint32_t max_prb); SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp_type, diff --git a/lib/include/srslte/phy/enb/enb_dl.h b/lib/include/srslte/phy/enb/enb_dl.h index 2b11bd6e3..5e0d2bf5e 100644 --- a/lib/include/srslte/phy/enb/enb_dl.h +++ b/lib/include/srslte/phy/enb/enb_dl.h @@ -69,15 +69,20 @@ typedef struct SRSLTE_API { cf_t *slot1_symbols[SRSLTE_MAX_PORTS]; srslte_ofdm_t ifft[SRSLTE_MAX_PORTS]; + + srslte_ofdm_t ifft_mbsfn; srslte_pbch_t pbch; srslte_pcfich_t pcfich; srslte_regs_t regs; srslte_pdcch_t pdcch; srslte_pdsch_t pdsch; + srslte_pmch_t pmch; srslte_phich_t phich; srslte_refsignal_t csr_signal; - srslte_pdsch_cfg_t pdsch_cfg; + srslte_refsignal_t mbsfnr_signal; + srslte_pdsch_cfg_t pdsch_cfg; + srslte_pdsch_cfg_t pmch_cfg; srslte_ra_dl_dci_t dl_dci; srslte_dci_format_t dci_format; @@ -134,6 +139,8 @@ SRSLTE_API void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q); SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp); +SRSLTE_API void srslte_enb_dl_set_non_mbsfn_region(srslte_enb_dl_t *q, uint8_t non_mbsfn_region); + SRSLTE_API void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q); SRSLTE_API void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, @@ -157,8 +164,13 @@ SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti); +SRSLTE_API void srslte_enb_dl_put_mbsfn_base(srslte_enb_dl_t *q, + uint32_t tti); + SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q); +SRSLTE_API void srslte_enb_dl_gen_signal_mbsfn(srslte_enb_dl_t *q); + SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti); @@ -174,6 +186,12 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type); +SRSLTE_API int srslte_enb_dl_put_pmch(srslte_enb_dl_t *q, + srslte_ra_dl_grant_t *grant, + srslte_softbuffer_tx_t *softbuffer, + uint32_t sf_idx, + uint8_t *data_mbms); + SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant, srslte_dci_format_t format, diff --git a/lib/include/srslte/phy/phch/pmch.h b/lib/include/srslte/phy/phch/pmch.h index 7d352e62a..22f1458a4 100644 --- a/lib/include/srslte/phy/phch/pmch.h +++ b/lib/include/srslte/phy/phch/pmch.h @@ -94,7 +94,7 @@ SRSLTE_API int srslte_pmch_init_multi(srslte_pmch_t *q, SRSLTE_API void srslte_pmch_free(srslte_pmch_t *q); - +SRSLTE_API int srslte_pmch_set_cell(srslte_pmch_t *q, srslte_cell_t cell); SRSLTE_API int srslte_pmch_set_area_id(srslte_pmch_t *q, uint16_t area_id); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 238cd1a18..0222357bb 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -212,9 +212,12 @@ int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q, uint16_t mbsfn_area_ if (mbsfn_area_id < SRSLTE_MAX_MBSFN_AREA_IDS) { if(!q->mbsfn_refs[mbsfn_area_id]) { q->mbsfn_refs[mbsfn_area_id] = calloc(1, sizeof(srslte_refsignal_t)); + if(srslte_refsignal_mbsfn_init(q->mbsfn_refs[mbsfn_area_id], q->cell.nof_prb)) { + return SRSLTE_ERROR; + } } if(q->mbsfn_refs[mbsfn_area_id]) { - if(srslte_refsignal_mbsfn_init(q->mbsfn_refs[mbsfn_area_id], q->cell, mbsfn_area_id)) { + if(srslte_refsignal_mbsfn_set_cell(q->mbsfn_refs[mbsfn_area_id], q->cell, mbsfn_area_id)) { return SRSLTE_ERROR; } } @@ -267,11 +270,11 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslt const float weight = 1.0f; float sum_power = 0.0f; uint32_t count = 0; - uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + uint32_t npilots = (ch_mode == SRSLTE_SF_MBSFN)?SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id):SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols() : srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = npilots / nsymbols; - uint32_t fidx = srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); + uint32_t fidx = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_fidx(1):srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); cf_t *input2d[nsymbols + 2]; cf_t *tmp_noise = q->tmp_noise; @@ -497,8 +500,10 @@ void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t *q, bool enable) { uint32_t srslte_chest_dl_interleave_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *tmp, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; - - if (srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0) < 3) { + uint32_t fidx = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_fidx(1):srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); + + + if (fidx < 3) { srslte_vec_interleave(input, &input[nref], tmp, nref); for (int l = 2; l < nsymbols - 1; l += 2) { srslte_vec_interleave_add(&input[l * nref], &input[(l + 1) * nref], tmp, nref); @@ -519,6 +524,7 @@ uint32_t srslte_chest_dl_interleave_pilots(srslte_chest_dl_t *q, cf_t *input, cf static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; + uint32_t fidx = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_fidx(1):srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); // Average in the time domain if enabled if (q->average_subframe) { @@ -549,9 +555,16 @@ static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint } } + + uint32_t skip = (ch_mode == SRSLTE_SF_MBSFN)?2*q->cell.nof_prb:0; + + if(ch_mode == SRSLTE_SF_MBSFN){ + memcpy(&output[0],&input[0],skip*sizeof(cf_t)); + } + // Average in the frequency domain for (int l=0;lsmooth_filter, &output[l*nref], nref, q->smooth_filter_len); + srslte_conv_same_cf(&input[l*nref + skip], q->smooth_filter, &output[l*nref + skip], nref, q->smooth_filter_len); } } @@ -660,11 +673,10 @@ int srslte_chest_dl_estimate_port_mbsfn(srslte_chest_dl_t *q, cf_t *input, cf_t srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx], q->pilot_estimates, (2*q->cell.nof_prb)); - srslte_vec_prod_conj_ccc(q->pilot_recv_signal+(2*q->cell.nof_prb), q->mbsfn_refs[mbsfn_area_id]->pilots[port_id/2][sf_idx], - q->pilot_estimates+(2*q->cell.nof_prb), SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id)-(2*q->cell.nof_prb)); + srslte_vec_prod_conj_ccc(&q->pilot_recv_signal[(2*q->cell.nof_prb)], q->mbsfn_refs[mbsfn_area_id]->pilots[port_id/2][sf_idx], + &q->pilot_estimates[(2*q->cell.nof_prb)], SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id)-(2*q->cell.nof_prb)); - chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_MBSFN); return 0; diff --git a/lib/src/phy/ch_estimation/refsignal_dl.c b/lib/src/phy/ch_estimation/refsignal_dl.c index 308be6877..316f84476 100644 --- a/lib/src/phy/ch_estimation/refsignal_dl.c +++ b/lib/src/phy/ch_estimation/refsignal_dl.c @@ -176,22 +176,21 @@ free_and_exit: } -int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, srslte_cell_t cell, uint16_t mbsfn_area_id) +int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; uint32_t i, p; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_refsignal_t)); - q->cell = cell; + q->type = SRSLTE_SF_MBSFN; - q->mbsfn_area_id = mbsfn_area_id; + for (p=0;p<2;p++) { for (i=0;ipilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * q->cell.nof_prb * 18); + q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * max_prb * 18); if (!q->pilots[p][i]) { perror("malloc"); goto free_and_exit; @@ -199,9 +198,7 @@ int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, srslte_cell_t cell, uint } } - if(srslte_refsignal_mbsfn_gen_seq(q, q->cell, q->mbsfn_area_id)) { - goto free_and_exit; - } + ret = SRSLTE_SUCCESS; } @@ -212,7 +209,24 @@ free_and_exit: return ret; } +int srslte_refsignal_mbsfn_set_cell(srslte_refsignal_t * q, srslte_cell_t cell, uint16_t mbsfn_area_id){ + + int ret = SRSLTE_ERROR_INVALID_INPUTS; + q->cell = cell; + q->mbsfn_area_id = mbsfn_area_id; + if(srslte_refsignal_mbsfn_gen_seq(q, q->cell, q->mbsfn_area_id)) { + goto free_and_exit; + } + + ret = SRSLTE_SUCCESS; + + free_and_exit: + if (ret == SRSLTE_ERROR) { + srslte_refsignal_free(q); + } + return ret; +} /** Allocates memory for the 20 slots in a subframe diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index 977f37892..adea1f5e5 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -149,6 +149,7 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof q->symbol_sz = (uint32_t) symbol_sz; q->nof_symbols = SRSLTE_CP_NSYMB(cp); + q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT); q->cp = cp; q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE; q->nof_guards = ((symbol_sz - q->nof_re) / 2); @@ -246,14 +247,15 @@ int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t return srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); } -int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb) +int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) { - int symbol_sz = srslte_symbol_sz(nof_prb); + int symbol_sz = srslte_symbol_sz(max_prb); if (symbol_sz < 0) { - fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb); return -1; } - return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); + q->max_prb = max_prb; + return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); } @@ -292,7 +294,7 @@ int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); return -1; } - + q->max_prb = nof_prb; ret = srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN); if (ret == SRSLTE_SUCCESS) { diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 9d33da26c..6d92db83a 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -69,6 +69,13 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], u goto clean_exit; } } + + + if (srslte_ofdm_tx_init_mbsfn(&q->ifft_mbsfn, SRSLTE_CP_EXT, q->sf_symbols[0], out_buffer[0], max_prb)) { + fprintf(stderr, "Error initiating FFT \n"); + goto clean_exit; + } + if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); @@ -82,7 +89,15 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], u fprintf(stderr, "Error creating PHICH object\n"); goto clean_exit; } + int mbsfn_area_id = 1; + + + if (srslte_pmch_init(&q->pmch, max_prb)) { + fprintf(stderr, "Error creating PMCH object\n"); + } + srslte_pmch_set_area_id(&q->pmch, mbsfn_area_id); + if (srslte_pdcch_init_enb(&q->pdcch, max_prb)) { fprintf(stderr, "Error creating PDCCH object\n"); goto clean_exit; @@ -97,7 +112,11 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], u fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); goto clean_exit; } - + + if (srslte_refsignal_mbsfn_init(&q->mbsfnr_signal, max_prb)) { + fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); + goto clean_exit; + } ret = SRSLTE_SUCCESS; } else { @@ -117,15 +136,16 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q) for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { srslte_ofdm_tx_free(&q->ifft[i]); } + srslte_ofdm_tx_free(&q->ifft_mbsfn); srslte_regs_free(&q->regs); srslte_pbch_free(&q->pbch); srslte_pcfich_free(&q->pcfich); srslte_phich_free(&q->phich); srslte_pdcch_free(&q->pdcch); srslte_pdsch_free(&q->pdsch); - + srslte_pmch_free(&q->pmch); srslte_refsignal_free(&q->csr_signal); - + srslte_refsignal_free(&q->mbsfnr_signal); for (int i=0;isf_symbols[i]) { free(q->sf_symbols[i]); @@ -159,6 +179,15 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell) return SRSLTE_ERROR; } } + + if (srslte_ofdm_tx_set_prb(&q->ifft_mbsfn, SRSLTE_CP_EXT, q->cell.nof_prb)) { + fprintf(stderr, "Error re-planning ifft_mbsfn\n"); + return SRSLTE_ERROR; + } + + srslte_ofdm_set_non_mbsfn_region(&q->ifft_mbsfn, 2); + //srslte_ofdm_set_normalize(&q->ifft_mbsfn, true); + if (srslte_pbch_set_cell(&q->pbch, q->cell)) { fprintf(stderr, "Error creating PBCH object\n"); return SRSLTE_ERROR; @@ -181,11 +210,21 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell) fprintf(stderr, "Error creating PDSCH object\n"); return SRSLTE_ERROR; } + + if (srslte_pmch_set_cell(&q->pmch, q->cell)) { + fprintf(stderr, "Error creating PMCH object\n"); + return SRSLTE_ERROR; + } if (srslte_refsignal_cs_set_cell(&q->csr_signal, q->cell)) { fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); return SRSLTE_ERROR; } + int mbsfn_area_id = 1; + if (srslte_refsignal_mbsfn_set_cell(&q->mbsfnr_signal, q->cell, mbsfn_area_id)) { + fprintf(stderr, "Error initializing MBSFNR signal (%d)\n",ret); + return SRSLTE_ERROR; + } /* Generate PSS/SSS signals */ srslte_pss_generate(q->pss_signal, cell.id%3); srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id); @@ -201,6 +240,11 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell) +void srslte_enb_dl_set_non_mbsfn_region(srslte_enb_dl_t *q, uint8_t non_mbsfn_region) +{ + srslte_ofdm_set_non_mbsfn_region(&q->ifft_mbsfn, non_mbsfn_region); +} + void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp) { q->tx_amp = amp; @@ -334,17 +378,30 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) } +void srslte_enb_dl_put_mbsfn_base(srslte_enb_dl_t *q, uint32_t tti) +{ + uint32_t sf_idx1 = tti%10; + srslte_enb_dl_put_pcfich(q, sf_idx1); + srslte_refsignal_mbsfn_put_sf(q->cell, 0,q->csr_signal.pilots[0][sf_idx1], q->mbsfnr_signal.pilots[0][sf_idx1], q->sf_symbols[0]); +} + void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q) { // TODO: PAPR control float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft[0].symbol_sz); - for (int i = 0; i < q->cell.nof_ports; i++) { - srslte_ofdm_tx_sf(&q->ifft[i]); - srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, q->tx_amp*norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + srslte_ofdm_tx_sf(&q->ifft[i]); + srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); } } +void srslte_enb_dl_gen_signal_mbsfn(srslte_enb_dl_t *q) +{ + float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft_mbsfn.symbol_sz); + srslte_ofdm_tx_sf(&q->ifft_mbsfn); + srslte_vec_sc_prod_cfc(q->ifft_mbsfn.out_buffer, norm_factor, q->ifft_mbsfn.out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); +} + int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti) { return srslte_pdsch_set_rnti(&q->pdsch, rnti); @@ -438,7 +495,23 @@ int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srs return SRSLTE_SUCCESS; } - +int srslte_enb_dl_put_pmch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer, uint32_t sf_idx, uint8_t *data_mbms) +{ + /* Encode PMCH */ + + int mbsfn_area_id = 1; + if (srslte_pmch_cfg(&q->pmch_cfg, q->cell, grant, q->cfi, sf_idx)) { + fprintf(stderr, "Error configuring PMCH\n"); + return SRSLTE_ERROR; + } + /* Encode PMCH */ + if (srslte_pmch_encode(&q->pmch, &q->pmch_cfg, softbuffer, data_mbms, mbsfn_area_id, q->sf_symbols)) { + fprintf(stderr, "Error encoding PDSCH\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} void srslte_enb_dl_save_signal(srslte_enb_dl_t *q, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi) { diff --git a/lib/src/phy/phch/pmch.c b/lib/src/phy/phch/pmch.c index 941d98a2f..b1560c7b1 100644 --- a/lib/src/phy/phch/pmch.c +++ b/lib/src/phy/phch/pmch.c @@ -264,12 +264,29 @@ void srslte_pmch_free(srslte_pmch_t *q) { } +int srslte_pmch_set_cell(srslte_pmch_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + q->max_re = q->cell.nof_prb * MAX_PMCH_RE; + + INFO("PMCH: Cell config PCI=%d, %d ports, %d PRBs, max_symbols: %d\n", q->cell.nof_ports, + q->cell.id, q->cell.nof_prb, q->max_re); + + ret = SRSLTE_SUCCESS; + } + return ret; +} /* Precalculate the scramble sequences for a given MBSFN area ID. This function takes a while * to execute. */ int srslte_pmch_set_area_id(srslte_pmch_t *q, uint16_t area_id) { - uint32_t i; + uint32_t i; if (!q->seqs[area_id]) { q->seqs[area_id] = calloc(1, sizeof(srslte_pmch_seq_t)); if (q->seqs[area_id]) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 98ff5c9fd..dc9fdc806 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -199,8 +199,10 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell) if (q != NULL && srslte_cell_isvalid(&cell)) { - q->pkt_errors = 0; - q->pkts_total = 0; + q->pdsch_pkt_errors = 0; + q->pdsch_pkts_total = 0; + q->pmch_pkt_errors = 0; + q->pmch_pkts_total = 0; q->pending_ul_dci_rnti = 0; if (q->cell.id != cell.id || q->cell.nof_prb == 0) { @@ -218,6 +220,12 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell) return SRSLTE_ERROR; } } + + if (srslte_ofdm_rx_set_prb(&q->fft_mbsfn, SRSLTE_CP_EXT, q->cell.nof_prb)) { + fprintf(stderr, "Error resizing MBSFN FFT\n"); + return SRSLTE_ERROR; + } + if (srslte_chest_dl_set_cell(&q->chest, q->cell)) { fprintf(stderr, "Error resizing channel estimator\n"); return SRSLTE_ERROR; @@ -237,9 +245,15 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell) } if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) { - fprintf(stderr, "Error creating PDSCH object\n"); + fprintf(stderr, "Error resizing PDSCH object\n"); return SRSLTE_ERROR; } + + if (srslte_pmch_set_cell(&q->pmch, q->cell)) { + fprintf(stderr, "Error resizing PMCH object\n"); + return SRSLTE_ERROR; + } + q->current_rnti = 0; } ret = SRSLTE_SUCCESS;