diff --git a/cmake/modules/BuildMex.cmake b/cmake/modules/BuildMex.cmake index ce5ce6c3d..83e971829 100644 --- a/cmake/modules/BuildMex.cmake +++ b/cmake/modules/BuildMex.cmake @@ -34,24 +34,24 @@ FUNCTION(BuildMex) cmake_parse_arguments(BuildMex "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (MATLAB_FOUND) add_library(${BuildMex_MEXNAME}-mat SHARED ${BuildMex_SOURCES}) - target_include_directories(${BuildMex_MEXNAME}-mat PUBLIC ${MATLAB_INCLUDE_DIR}) + #target_include_directories(${BuildMex_MEXNAME}-mat PUBLIC ${MATLAB_INCLUDE_DIR}) set_target_properties(${BuildMex_MEXNAME}-mat PROPERTIES SUFFIX "${MATLAB_MEX_EXTENSION}" PREFIX "liblte_" OUTPUT_NAME "${BuildMex_MEXNAME}" - COMPILE_FLAGS "-fvisibility=default ${MATLAB_MEX_CFLAGS}" + COMPILE_FLAGS "-fvisibility=default ${MATLAB_MEX_CFLAGS} -I${MATLAB_INCLUDE_DIR}" ) target_link_libraries(${BuildMex_MEXNAME}-mat ${BuildMex_LIBRARIES} ${MATLAB_MEX_LIBRARY}) install(TARGETS ${BuildMex_MEXNAME}-mat DESTINATION "${MEX_DIR}/liblte/") endif(MATLAB_FOUND) if (OCTAVE_FOUND) add_library(${BuildMex_MEXNAME}-oct SHARED ${BuildMex_SOURCES}) - target_include_directories(${BuildMex_MEXNAME}-oct PUBLIC ${OCTAVE_INCLUDE_DIR}) + #target_include_directories(${BuildMex_MEXNAME}-oct PUBLIC ${OCTAVE_INCLUDE_DIR}) set_target_properties(${BuildMex_MEXNAME}-oct PROPERTIES SUFFIX ".${OCTAVE_MEXFILE_EXT}" PREFIX "liblte_" OUTPUT_NAME "${BuildMex_MEXNAME}" - COMPILE_FLAGS "-fvisibility=default ${OCTAVE_MEX_CFLAGS} -DUNDEF_BOOL" + COMPILE_FLAGS "-fvisibility=default ${OCTAVE_MEX_CFLAGS} -DUNDEF_BOOL -I${OCTAVE_INCLUDE_DIR}" ) target_link_libraries(${BuildMex_MEXNAME}-oct ${BuildMex_LIBRARIES} ${OCTAVE_LIBRARIES}) install(TARGETS ${BuildMex_MEXNAME}-oct DESTINATION "${MEX_DIR}/liblte/") diff --git a/cuhd/lib/cuhd_imp.cpp b/cuhd/lib/cuhd_imp.cpp index cf0e5b64d..53be35156 100644 --- a/cuhd/lib/cuhd_imp.cpp +++ b/cuhd/lib/cuhd_imp.cpp @@ -36,6 +36,8 @@ //#define METADATA_VERBOSE +//#define HIDE_MESSAGES + void my_handler(uhd::msg::type_t type, const std::string & msg) { //handle the message... @@ -124,8 +126,10 @@ int cuhd_open(char *args, void **h) // handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=50000000" + ", num_recv_frames=512"); handler->usrp->set_clock_source("internal"); +#ifdef HIDE_MESSAGES uhd::msg::register_handler(my_handler); - +#endif + std::string otw, cpu; otw = "sc16"; cpu = "fc32"; diff --git a/lte/examples/pdsch_enodeb.c b/lte/examples/pdsch_enodeb.c index be5e93298..49548fb15 100644 --- a/lte/examples/pdsch_enodeb.c +++ b/lte/examples/pdsch_enodeb.c @@ -60,12 +60,12 @@ lte_cell_t cell = { int net_port = -1; // -1 generates random data -uint32_t cfi=1; +uint32_t cfi=2; uint32_t mcs_idx = 1, last_mcs_idx = 1; int nof_frames = -1; char *uhd_args = ""; -float uhd_amp = 0.1, uhd_gain = 70.0, uhd_freq = 2400000000; +float uhd_amp = 0.03, uhd_gain = 70.0, uhd_freq = 2400000000; bool null_file_sink=false; filesink_t fsink; @@ -303,12 +303,13 @@ reverse(register unsigned int x) uint32_t prbset_to_bitmask() { uint32_t mask=0; - for (int i=0;i= prbset_orig && i < prbset_orig + prbset_num) { mask = mask | (0x1<>(32-cell.nof_prb); + return reverse(mask)>>(32-nb); } int update_radl() { @@ -324,10 +325,11 @@ int update_radl() { 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_mcs_from_idx_dl(mcs_idx, prb_alloc.slot[0].nof_prb, &ra_dl.mcs); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); + pdsch_harq_reset(&harq_process); if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &prb_alloc)) { fprintf(stderr, "Error configuring HARQ process\n"); return -1; @@ -355,7 +357,7 @@ int update_control() { if(input[0] == 27) { switch(input[2]) { case RIGHT_KEY: - if (prbset_orig + prbset_num < cell.nof_prb) + if (prbset_orig + prbset_num < (int) ceilf((float) cell.nof_prb / ra_type0_P(cell.nof_prb))) prbset_orig++; break; case LEFT_KEY: @@ -363,7 +365,7 @@ int update_control() { prbset_orig--; break; case UP_KEY: - if (prbset_num < cell.nof_prb) + if (prbset_num < (int) ceilf((float) cell.nof_prb / ra_type0_P(cell.nof_prb))) prbset_num++; break; case DOWN_KEY: @@ -372,6 +374,7 @@ int update_control() { prbset_num--; break; } + printf("num: %d, orig: %d\n", prbset_num, prbset_orig); } else { last_mcs_idx = mcs_idx; mcs_idx = atoi(input); @@ -408,7 +411,7 @@ void *net_thread_fnc(void *arg) { if (n > 0) { int nbytes = 1+(ra_dl.mcs.tbs-1)/8; rpm += n; - printf("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); + INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); wpm = 0; while (rpm >= nbytes) { // wait for packet to be transmitted @@ -423,7 +426,9 @@ void *net_thread_fnc(void *arg) { INFO("%d bytes left in buffer for next packet\n", rpm); memcpy(data_unpacked, &data_unpacked[wpm], rpm * sizeof(uint8_t)); } - } else if (n < 0) { + } else if (n == 0) { + rpm = 0; + } else { fprintf(stderr, "Error receiving from network\n"); exit(-1); } @@ -441,7 +446,7 @@ int main(int argc, char **argv) { cf_t *sf_symbols[MAX_PORTS]; cf_t *slot1_symbols[MAX_PORTS]; dci_msg_t dci_msg; - dci_location_t locations[NSUBFRAMES_X_FRAME][10]; + dci_location_t locations[NSUBFRAMES_X_FRAME][30]; uint32_t sfn; chest_dl_t est; @@ -462,8 +467,8 @@ int main(int argc, char **argv) { cell.phich_resources = R_1; sfn = 0; - prbset_num = cell.nof_prb; - last_prbset_num = cell.nof_prb; + prbset_num = (int) ceilf((float) cell.nof_prb / ra_type0_P(cell.nof_prb)); + last_prbset_num = prbset_num; /* this *must* be called after setting slot_len_* */ base_init(); @@ -506,7 +511,8 @@ int main(int argc, char **argv) { /* Initiate valid DCI locations */ for (i=0;i 0) { if (netsink_init(&net_sink_signal, prog_args.net_address_signal, prog_args.net_port_signal, NETSINK_UDP)) { fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address_signal, prog_args.net_port_signal); exit(-1); } + netsink_set_nonblocking(&net_sink_signal); } #ifndef DISABLE_UHD @@ -351,14 +354,7 @@ int main(int argc, char **argv) { if (ret < 0) { fprintf(stderr, "Error calling ue_sync_work()\n"); } - - if (prog_args.net_port_signal > 0) { - if (netsink_write(&net_sink_signal, sf_buffer, ue_sync_sf_len(&ue_sync)) < 0) { - fprintf(stderr, "Error sending data through UDP socket\n"); - perror("write"); - } - } - + /* ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */ if (ret == 1) { switch (state) { @@ -403,7 +399,7 @@ int main(int argc, char **argv) { if (prog_args.net_port > 0) { bit_unpack_vector(data_packed, data, n); if (netsink_write(&net_sink, data, 1+(n-1)/8) < 0) { - fprintf(stderr, "Error sending data through UDP socket\n"); + fprintf(stderr, "Error sending data through socket\n"); } } } @@ -411,31 +407,38 @@ int main(int argc, char **argv) { rsrq = VEC_EMA(chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.05); rsrp = VEC_EMA(chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05); - snr = VEC_EMA(chest_dl_get_snr(&ue_dl.chest), snr, 0.05); + snr = VEC_EMA(chest_dl_get_snr(&ue_dl.chest), snr, 0.01); nframes++; if (isnan(rsrq)) { rsrq = 0; } + if (isnan(snr)) { + snr = 0; + } + if (isnan(rsrp)) { + rsrp = 0; + } } if (ue_sync_get_sfidx(&ue_sync) != 5 && ue_sync_get_sfidx(&ue_sync) != 0) { pdcch_tx++; } + // Plot and Printf if (ue_sync_get_sfidx(&ue_sync) == 5) { #ifdef STDOUT_COMPACT - printf("SFN: %4d, PDCCH-Miss: %5.2f%% (%d), PDSCH-BLER: %5.2f%% (%d blocks)\r", - sfn, 100*(1-(float) ue_dl.nof_pdcch_detected/nof_trials),ue_dl.nof_pdcch_detected-pdcch_tx, - (float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,nof_trials, ue_dl.pkts_total); + printf("SFN: %4d, PDCCH-Miss: %5.2f%% (%d missed), PDSCH-BLER: %5.2f%% (%d errors)\r", + sfn, 100*(1-(float) ue_dl.nof_pdcch_detected/nof_trials),pdcch_tx-ue_dl.nof_pdcch_detected, + (float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,ue_dl.pkt_errors); #else printf("CFO: %+8.4f KHz, SFO: %+8.4f Khz, " "RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %4.1f dB, " - "PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%% (%d blocks)\r", + "PDCCH-Miss: %5.2f%% (%d missed), PDSCH-BLER: %5.2f%% (%d errors)\r", ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000, 10*log10(rsrp*1000)-gain_offset, 10*log10(rsrq), 10*log10(snr), - 100*(1-(float) ue_dl.nof_pdcch_detected/nof_trials), - (float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,nof_trials, ue_dl.pkts_total); + 100*(1-(float) ue_dl.nof_pdcch_detected/nof_trials), pdcch_tx-ue_dl.nof_pdcch_detected, + (float) 100*ue_dl.pkt_errors/ue_dl.pkts_total, ue_dl.pkt_errors); #endif } @@ -447,6 +450,7 @@ int main(int argc, char **argv) { sfn = 0; } } + #ifndef DISABLE_GRAPHICS if (!prog_args.disable_plots) { plot_sf_idx = ue_sync_get_sfidx(&ue_sync); @@ -488,7 +492,7 @@ int main(int argc, char **argv) { #ifndef DISABLE_GRAPHICS -plot_waterfall_t poutfft; +//plot_waterfall_t poutfft; plot_real_t p_sync, pce; plot_scatter_t pscatequal, pscatequal_pdcch; @@ -516,9 +520,9 @@ void *plot_thread_run(void *arg) { tmp_plot2[i] = -80; } } - for (i=0;i 0) { + if (netsink_write(&net_sink_signal, &sf_buffer[ue_sync_sf_len(&ue_sync)/7], + ue_sync_sf_len(&ue_sync)) < 0) + { + fprintf(stderr, "Error sending data through UDP socket\n"); + perror("write"); + } + } + } + } return NULL; @@ -542,9 +557,9 @@ void init_plots() { plot_init(); - plot_waterfall_init(&poutfft, RE_X_RB * ue_dl.cell.nof_prb, 1000); - plot_waterfall_setTitle(&poutfft, "Output FFT - Magnitude"); - plot_waterfall_setPlotYAxisScale(&poutfft, -40, 40); + //plot_waterfall_init(&poutfft, RE_X_RB * ue_dl.cell.nof_prb, 1000); + //plot_waterfall_setTitle(&poutfft, "Output FFT - Magnitude"); + //plot_waterfall_setPlotYAxisScale(&poutfft, -40, 40); plot_real_init(&pce); plot_real_setTitle(&pce, "Channel Response - Magnitude"); diff --git a/lte/phy/include/liblte/phy/io/netsink.h b/lte/phy/include/liblte/phy/io/netsink.h index ef36dd81e..45e2e14ea 100644 --- a/lte/phy/include/liblte/phy/io/netsink.h +++ b/lte/phy/include/liblte/phy/io/netsink.h @@ -34,17 +34,20 @@ #include #include #include +#include #include "liblte/config.h" +typedef enum {NETSINK_UDP, NETSINK_TCP} netsink_type_t; + /* Low-level API */ typedef struct LIBLTE_API { int sockfd; + bool connected; + netsink_type_t type; struct sockaddr_in servaddr; }netsink_t; -typedef enum {NETSINK_UDP, NETSINK_TCP} netsink_type_t; - LIBLTE_API int netsink_init(netsink_t *q, char *address, int port, @@ -56,6 +59,8 @@ LIBLTE_API int netsink_write(netsink_t *q, void *buffer, int nof_bytes); +LIBLTE_API int netsink_set_nonblocking(netsink_t *q); + /* High-level API */ typedef struct LIBLTE_API { diff --git a/lte/phy/include/liblte/phy/phch/pdsch.h b/lte/phy/include/liblte/phy/phch/pdsch.h index 826c4a2af..0a6cd46f1 100644 --- a/lte/phy/include/liblte/phy/phch/pdsch.h +++ b/lte/phy/include/liblte/phy/phch/pdsch.h @@ -43,7 +43,7 @@ #include "liblte/phy/phch/dci.h" #include "liblte/phy/phch/regs.h" -#define TDEC_MAX_ITERATIONS 6 +#define TDEC_MAX_ITERATIONS 5 typedef _Complex float cf_t; diff --git a/lte/phy/include/liblte/phy/utils/vector.h b/lte/phy/include/liblte/phy/utils/vector.h index ed6fa8a09..00671534b 100644 --- a/lte/phy/include/liblte/phy/utils/vector.h +++ b/lte/phy/include/liblte/phy/utils/vector.h @@ -43,7 +43,7 @@ typedef _Complex float cf_t; #define VEC_CMA(data, average, n) ((average) + ((data) - (average)) / ((n)+1)) // Exponential moving average -#define VEC_EMA(data, average, alpha) (average)==0?(data):((alpha)*(data)+(1-alpha)*(average)) +#define VEC_EMA(data, average, alpha) ((alpha)*(data)+(1-alpha)*(average)) /** Return the sum of all the elements */ LIBLTE_API int vec_acc_ii(int *x, uint32_t len); diff --git a/lte/phy/lib/ch_estimation/src/chest_dl.c b/lte/phy/lib/ch_estimation/src/chest_dl.c index 657a2ed33..3e38935d1 100644 --- a/lte/phy/lib/ch_estimation/src/chest_dl.c +++ b/lte/phy/lib/ch_estimation/src/chest_dl.c @@ -43,6 +43,8 @@ #define CHEST_RS_AVERAGE_TIME 2 #define CHEST_RS_AVERAGE_FREQ 3 +#define NOISE_POWER_USE_ESTIMATES + /** 3GPP LTE Downlink channel estimator and equalizer. * Estimates the channel in the resource elements transmitting references and interpolates for the rest @@ -115,15 +117,14 @@ int chest_dl_init(chest_dl_t *q, lte_cell_t cell) } /* Set default time/freq filters */ - float f[3]={0.1, 0.8, 0.1}; - chest_dl_set_filter_freq(q, f, 3); + //float f[3]={0.1, 0.8, 0.1}; + //chest_dl_set_filter_freq(q, f, 3); - //float f[5]={0.05, 0.15, 0.6, 0.15, 0.05}; - //chest_dl_set_filter_freq(q, f, 5); + float f[5]={0.05, 0.15, 0.6, 0.15, 0.05}; + chest_dl_set_filter_freq(q, f, 5); - //float t[2]={0.1, 0.9}; - float t[1] = {1.0}; - chest_dl_set_filter_time(q, t, 1); + float t[2]={0.15, 0.85}; + chest_dl_set_filter_time(q, t, 2); q->cell = cell; } @@ -194,6 +195,10 @@ int chest_dl_set_filter_time(chest_dl_t *q, float *filter, uint32_t filter_len) } + +#ifdef NOISE_POWER_USE_ESTIMATES + +/* Uses the difference between the averaged and non-averaged pilot estimates */ static float estimate_noise_port(chest_dl_t *q, uint32_t port_id, cf_t *avg_pilots) { /* Use difference between averaged and noisy LS pilot estimates */ vec_sub_ccc(avg_pilots, q->pilot_estimates[port_id], @@ -202,6 +207,22 @@ static float estimate_noise_port(chest_dl_t *q, uint32_t port_id, cf_t *avg_pilo return vec_avg_power_cf(q->tmp_noise, REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); } +#else + +/* Uses the 5 empty transmitted SC before and after the SSS and PSS sequences for noise estimation */ +static float estimate_noise_empty_sc(chest_dl_t *q, cf_t *input) { + int k_sss = (CP_NSYMB(q->cell.cp) - 2) * q->cell.nof_prb * RE_X_RB + q->cell.nof_prb * RE_X_RB / 2 - 31; + float noise_power = 0; + noise_power += vec_avg_power_cf(&input[k_sss-5], 5); // 5 empty SC before SSS + noise_power += vec_avg_power_cf(&input[k_sss+62], 5); // 5 empty SC after SSS + int k_pss = (CP_NSYMB(q->cell.cp) - 1) * q->cell.nof_prb * RE_X_RB + q->cell.nof_prb * RE_X_RB / 2 - 31; + noise_power += vec_avg_power_cf(&input[k_pss-5], 5); // 5 empty SC before PSS + noise_power += vec_avg_power_cf(&input[k_pss+62], 5); // 5 empty SC after PSS + + return noise_power; +} +#endif + #define pilot_est(idx) q->pilot_estimates[port_id][REFSIGNAL_PILOT_IDX(idx,l,q->cell)] #define pilot_avg(idx) q->pilot_estimates_average[port_id][REFSIGNAL_PILOT_IDX(idx,l,q->cell)] #define pilot_tmp(idx) q->tmp_freqavg[REFSIGNAL_PILOT_IDX(idx,l,q->cell)] @@ -227,11 +248,6 @@ static void average_pilots(chest_dl_t *q, uint32_t port_id) } } - /* Compute noise estimation before time averaging. - * FIXME: Apparently the noise estimation performance is better with frequency averaging only - */ - q->noise_estimate[port_id] = estimate_noise_port(q, port_id, q->tmp_freqavg); - for (l=0;lfilter_time_len > 0) { @@ -252,6 +268,10 @@ static void average_pilots(chest_dl_t *q, uint32_t port_id) memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t)); } } +#ifdef NOISE_POWER_USE_ESTIMATES + q->noise_estimate[port_id] = estimate_noise_port(q, port_id, q->pilot_estimates_average[port_id]); +#endif + } #define cesymb(i) ce[RE_IDX(q->cell.nof_prb,i,0)] @@ -308,6 +328,8 @@ float chest_dl_rssi(chest_dl_t *q, cf_t *input, uint32_t port_id) { return rssi/nsymbols; } +//#define RSRP_FROM_ESTIMATES + float chest_dl_rsrp(chest_dl_t *q, uint32_t port_id) { #ifdef RSRP_FROM_ESTIMATES return vec_avg_power_cf(q->pilot_estimates[port_id], @@ -341,7 +363,10 @@ int chest_dl_estimate_port(chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx if (ce != NULL) { interpolate_pilots(q, ce, port_id); } - + +#ifndef NOISE_POWER_USE_ESTIMATES + q->noise_estimate[port_id] = estimate_noise_empty_sc(q, input); +#endif return 0; } @@ -361,7 +386,11 @@ float chest_dl_get_noise_estimate(chest_dl_t *q) { float chest_dl_get_snr(chest_dl_t *q) { // Uses RSRP as an estimation of the useful signal power - return chest_dl_get_rsrp(q)/chest_dl_get_noise_estimate(q); +#ifdef NOISE_POWER_USE_ESTIMATES + return chest_dl_get_rsrp(q)/chest_dl_get_noise_estimate(q)/sqrt(2*lte_symbol_sz(q->cell.nof_prb)); +#else + return chest_dl_get_rsrp(q)/chest_dl_get_noise_estimate(q)/sqrt(2); +#endif } float chest_dl_get_rssi(chest_dl_t *q) { diff --git a/lte/phy/lib/ch_estimation/test/chest_test_dl_mex.c b/lte/phy/lib/ch_estimation/test/chest_test_dl_mex.c index 165677538..ed8e8f7ba 100644 --- a/lte/phy/lib/ch_estimation/test/chest_test_dl_mex.c +++ b/lte/phy/lib/ch_estimation/test/chest_test_dl_mex.c @@ -196,7 +196,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } /* Loop through the 10 subframes */ - if (chest_dl_estimate(&chest, input_signal, ce, sf_idx)) { + if (chest_dl_estimate(&chest, input_signal, ce, sf_idx)) { mexErrMsgTxt("Error running channel estimator\n"); return; } @@ -244,7 +244,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } if (nlhs >= 4) { - plhs[3] = mxCreateDoubleScalar(chest_dl_get_snr(&chest)); + plhs[3] = mxCreateDoubleScalar(chest_dl_get_noise_estimate(&chest)); } return; diff --git a/lte/phy/lib/io/src/netsink.c b/lte/phy/lib/io/src/netsink.c index 80fe5a22d..f01525264 100644 --- a/lte/phy/lib/io/src/netsink.c +++ b/lte/phy/lib/io/src/netsink.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include "liblte/phy/io/netsink.h" @@ -40,8 +42,7 @@ int netsink_init(netsink_t *q, char *address, int port, netsink_type_t type) { bzero(q, sizeof(netsink_t)); - q->sockfd=socket(AF_INET, type==NETSINK_TCP?SOCK_STREAM:SOCK_DGRAM,0); - + q->sockfd=socket(AF_INET, type==NETSINK_TCP?SOCK_STREAM:SOCK_DGRAM,0); if (q->sockfd < 0) { perror("socket"); return -1; @@ -50,13 +51,9 @@ int netsink_init(netsink_t *q, char *address, int port, netsink_type_t type) { q->servaddr.sin_family = AF_INET; q->servaddr.sin_addr.s_addr=inet_addr(address); q->servaddr.sin_port=htons(port); + q->connected = false; + q->type = type; - printf("Connecting to %s:%d\n", address, port); - if (connect(q->sockfd,&q->servaddr,sizeof(q->servaddr)) < 0) { - perror("connect"); - return -1; - } - return 0; } @@ -67,8 +64,45 @@ void netsink_free(netsink_t *q) { bzero(q, sizeof(netsink_t)); } +int netsink_set_nonblocking(netsink_t *q) { + if (fcntl(q->sockfd, F_SETFL, O_NONBLOCK)) { + perror("fcntl"); + return -1; + } + return 0; +} + int netsink_write(netsink_t *q, void *buffer, int nof_bytes) { - return write(q->sockfd, buffer, nof_bytes); + if (!q->connected) { + if (connect(q->sockfd,&q->servaddr,sizeof(q->servaddr)) < 0) { + if (errno == ECONNREFUSED || errno == EINPROGRESS) { + return 0; + } else { + perror("connect"); + exit(-1); + return -1; + } + } else { + q->connected = true; + } + } + int n = 0; + if (q->connected) { + n = write(q->sockfd, buffer, nof_bytes); + if (n < 0) { + if (errno == ECONNRESET) { + close(q->sockfd); + q->sockfd=socket(AF_INET, q->type==NETSINK_TCP?SOCK_STREAM:SOCK_DGRAM,0); + if (q->sockfd < 0) { + perror("socket"); + return -1; + } + q->connected = false; + return 0; + } + } + } + return n; } diff --git a/lte/phy/lib/io/src/netsource.c b/lte/phy/lib/io/src/netsource.c index b28d5f035..23cc35eca 100644 --- a/lte/phy/lib/io/src/netsource.c +++ b/lte/phy/lib/io/src/netsource.c @@ -93,15 +93,14 @@ int netsource_read(netsource_t *q, void *buffer, int nbytes) { } } int n = read(q->connfd, buffer, nbytes); + if (n == 0) { + printf("Connection closed\n"); + close(q->connfd); + q->connfd = 0; + return 0; + } if (n == -1) { - if (errno == ECONNRESET) { - printf("Connection closed\n"); - close(q->connfd); - q->connfd = 0; - return 0; - } else { - perror("read"); - } + perror("read"); } return n; } diff --git a/lte/phy/lib/phch/src/pdcch.c b/lte/phy/lib/phch/src/pdcch.c index 14bab3a6b..4d18828c7 100644 --- a/lte/phy/lib/phch/src/pdcch.c +++ b/lte/phy/lib/phch/src/pdcch.c @@ -435,7 +435,6 @@ int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float n - static void crc_set_mask_rnti(uint8_t *crc, uint16_t rnti) { uint32_t i; uint8_t mask[16]; diff --git a/lte/phy/lib/sync/src/pss.c b/lte/phy/lib/sync/src/pss.c index 62e7f4e23..7eab9ab3b 100644 --- a/lte/phy/lib/sync/src/pss.c +++ b/lte/phy/lib/sync/src/pss.c @@ -338,7 +338,7 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value) int pl_lb; if (corr_peak_pos > 0) { pl_lb = corr_peak_pos-1; - while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { + while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { pl_lb --; } } else { diff --git a/lte/phy/lib/ue/src/ue_dl.c b/lte/phy/lib/ue/src/ue_dl.c index 472a6c7f0..c0f48a10b 100644 --- a/lte/phy/lib/ue/src/ue_dl.c +++ b/lte/phy/lib/ue/src/ue_dl.c @@ -217,6 +217,10 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, q->current_rnti); formats = ue_formats; nof_formats = nof_ue_formats; + if (q->current_rnti == 1234) { + nof_locations = 1; + nof_formats = 1; + } } /* Extract all PDCCH symbols and get LLRs */ @@ -256,7 +260,7 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui ret = pdsch_decode(&q->pdsch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), data, sf_idx, - &q->harq_process[0], rvidx); + &q->harq_process[0], rvidx); if (ret == LIBLTE_ERROR) { q->pkt_errors++; } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) { @@ -280,7 +284,7 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui mean_exec_time = (float) VEC_EMA((float) t[0].tv_usec, mean_exec_time, 0.01); - if (found_dci > 0 && ret == LIBLTE_SUCCESS) { + if (found_dci > 0 && ret == LIBLTE_SUCCESS) { return ra_dl.mcs.tbs; } else { return 0; diff --git a/lte/phy/lib/ue/src/ue_sync.c b/lte/phy/lib/ue/src/ue_sync.c index 1add14476..e5944f9cb 100644 --- a/lte/phy/lib/ue/src/ue_sync.c +++ b/lte/phy/lib/ue/src/ue_sync.c @@ -259,6 +259,7 @@ static int find_peak_ok(ue_sync_t *q) { q->frame_no_cnt = 0; q->frame_total_cnt = 0; q->frame_find_cnt = 0; + q->mean_time_offset = 0; /* Set tracking CFO average to find CFO */ q->strack.mean_cfo = q->sfind.mean_cfo; @@ -289,10 +290,13 @@ static int track_peak_ok(ue_sync_t *q, uint32_t track_idx) { INFO("Time offset adjustment: %d samples\n", q->time_offset); } + /* compute cumulative moving average time offset */ + q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt); + /* If the PSS peak is beyond the frame (we sample too slowly), discard the offseted samples to align next frame */ if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) { - INFO("Positive time offset %d samples. Adjusting now.\n", q->time_offset); + INFO("\nPositive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset); if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset) < 0) { fprintf(stderr, "Error receiving from USRP\n"); return LIBLTE_ERROR; @@ -300,9 +304,6 @@ static int track_peak_ok(ue_sync_t *q, uint32_t track_idx) { q->time_offset = 0; } - /* compute cumulative moving average time offset */ - q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt); - q->peak_idx = q->sf_len/2 + q->time_offset; q->frame_ok_cnt++; q->frame_no_cnt = 0; @@ -335,7 +336,6 @@ static int receive_samples(ue_sync_t *q) { q->time_offset = -q->time_offset; } - INFO("Receiving %d samples\n", q->frame_len - q->time_offset); /* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */ if (q->recv_callback(q->stream, &q->input_buffer[q->time_offset], q->frame_len - q->time_offset) < 0) { return LIBLTE_ERROR; @@ -450,6 +450,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) { q->input_buffer, q->input_buffer, -sync_get_cfo(&q->strack) / q->fft_size); + } *sf_symbols = q->input_buffer; diff --git a/matlab/tests/equalizer_test.m b/matlab/tests/equalizer_test.m index 26e2007ff..c5ccc21ac 100644 --- a/matlab/tests/equalizer_test.m +++ b/matlab/tests/equalizer_test.m @@ -14,7 +14,7 @@ postEVM_liblte = zeros(length(SNR_values_db),Nrealizations); enb.NDLRB = 6; % Number of resource blocks -enb.CellRefP = 2; % One transmit antenna port +enb.CellRefP = 1; % One transmit antenna port enb.NCellID = 0; % Cell ID enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix enb.DuplexMode = 'FDD'; % FDD @@ -101,6 +101,8 @@ for sf = 0:10 end +txGrid([1:5 68:72],6:7) = zeros(10,2); + %% OFDM Modulation [txWaveform,info] = lteOFDMModulate(enb,txGrid); @@ -118,7 +120,7 @@ SNR = 10^(SNRdB/20); % Linear SNR cfg.SamplingRate = info.SamplingRate; % Pass data through the fading channel model -rxWaveform = lteFadingChannel(cfg,txWaveform); +%rxWaveform = lteFadingChannel(cfg,txWaveform); rxWaveform = txWaveform; %% Additive Noise @@ -149,14 +151,19 @@ addpath('../../debug/lte/phy/lib/ch_estimation/test') [estChannel, noiseEst(snr_idx)] = lteDLChannelEstimate(enb,cec,rxGrid); output=[]; snrest = zeros(10,1); -for i=0:9 + +nulls = rxGrid([1:5 68:72],6:7); +noiseEst(snr_idx) = var(nulls(:)); + +%for i=0:9 + i=0; % if (SNR_values_db(snr_idx) < 25) - [d, a, out, snrest(i+1)] = liblte_chest(enb.NCellID,enb.CellRefP,rxGrid(:,i*14+1:(i+1)*14),[0.15 0.7 0.15],[],i); + [d, a, out, snrest(i+1)] = liblte_chest(enb.NCellID,enb.CellRefP,rxGrid(:,i*14+1:(i+1)*14),[0.1 0.8 0.1],[0.1 0.9],i); % else % [d, a, out, snrest(i+1)] = liblte_chest(enb.NCellID,enb.CellRefP,rxGrid(:,i*14+1:(i+1)*14),[0.05 0.9 0.05],[],i); % end output = [output out]; -end +%end SNRest(snr_idx)=mean(snrest); disp(10*log10(SNRest(snr_idx))) %% MMSE Equalization @@ -196,8 +203,8 @@ end % % subplot(1,2,2) %SNR_liblte = 1./(SNRest*sqrt(2.0*enb.CellRefP*double(info.Nfft))); -SNR_liblte = SNRest; -SNR_matlab = 1./(noiseEst*sqrt(2.0*enb.CellRefP*double(info.Nfft))); +SNR_liblte = 1./(SNRest*sqrt(2.0)); +SNR_matlab = 1./(noiseEst*sqrt(2.0)); plot(SNR_values_db, SNR_values_db, SNR_values_db, 10*log10(SNR_liblte),SNR_values_db, 10*log10(SNR_matlab)) %plot(SNR_values_db, 10*log10(noiseTx), SNR_values_db, 10*log10(SNRest),SNR_values_db, 10*log10(noiseEst)) diff --git a/mex/lib/CMakeLists.txt b/mex/lib/CMakeLists.txt index 9eaba77e5..cf9c6dcc8 100644 --- a/mex/lib/CMakeLists.txt +++ b/mex/lib/CMakeLists.txt @@ -50,10 +50,10 @@ IF (MATLAB_FOUND OR OCTAVE_FOUND) INSTALL(TARGETS liblte_mex DESTINATION ${LIBRARY_DIR}) LIBLTE_SET_PIC(liblte_mex) if (MATLAB_FOUND) - target_include_directories(liblte_mex PUBLIC ${MATLAB_INCLUDE_DIR}) + include_directories(${MATLAB_INCLUDE_DIR}) endif(MATLAB_FOUND) if (OCTAVE_FOUND) - target_include_directories(liblte_mex PUBLIC ${OCTAVE_INCLUDE_DIR}) + include_directories(${OCTAVE_INCLUDE_DIR}) endif (OCTAVE_FOUND) ELSEIF (MATLAB_FOUND OR OCTAVE_FOUND)