PDSCH Video demo working
This commit is contained in:
parent
40c7db7009
commit
605f102682
|
@ -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/")
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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<cell.nof_prb;i++) {
|
||||
int nb = (int) ceilf((float) cell.nof_prb / ra_type0_P(cell.nof_prb));
|
||||
for (int i=0;i<nb;i++) {
|
||||
if (i >= prbset_orig && i < prbset_orig + prbset_num) {
|
||||
mask = mask | (0x1<<i);
|
||||
}
|
||||
}
|
||||
return reverse(mask)>>(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<NSUBFRAMES_X_FRAME;i++) {
|
||||
pdcch_ue_locations(&pdcch, locations[i], 10, i, cfi, 1234);
|
||||
pdcch_ue_locations(&pdcch, locations[i], 30, i, cfi, 1234);
|
||||
|
||||
}
|
||||
|
||||
nf = 0;
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "cuhd_utils.h"
|
||||
#endif
|
||||
|
||||
#define STDOUT_COMPACT
|
||||
//#define STDOUT_COMPACT
|
||||
|
||||
#ifndef DISABLE_GRAPHICS
|
||||
#include "liblte/graphics/plot.h"
|
||||
|
@ -215,19 +215,20 @@ ue_dl_t ue_dl;
|
|||
ue_sync_t ue_sync;
|
||||
prog_args_t prog_args;
|
||||
|
||||
uint32_t sfn = 0; // system frame number
|
||||
cf_t *sf_buffer;
|
||||
netsink_t net_sink, net_sink_signal;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int ret;
|
||||
cf_t *sf_buffer;
|
||||
lte_cell_t cell;
|
||||
int64_t sf_cnt;
|
||||
ue_mib_t ue_mib;
|
||||
void *uhd;
|
||||
uint32_t nof_trials = 0;
|
||||
uint32_t sfn = 0; // system frame number
|
||||
int n;
|
||||
uint8_t bch_payload[BCH_PAYLOAD_LEN], bch_payload_unpacked[BCH_PAYLOAD_LEN];
|
||||
uint32_t sfn_offset;
|
||||
netsink_t net_sink, net_sink_signal;
|
||||
|
||||
parse_args(&prog_args, argc, argv);
|
||||
|
||||
|
@ -236,12 +237,14 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port);
|
||||
exit(-1);
|
||||
}
|
||||
netsink_set_nonblocking(&net_sink);
|
||||
}
|
||||
if (prog_args.net_port_signal > 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<CP_NSYMB(ue_dl.cell.cp);i++) {
|
||||
plot_waterfall_appendNewData(&poutfft, &tmp_plot[i*RE_X_RB*ue_dl.cell.nof_prb], RE_X_RB*ue_dl.cell.nof_prb);
|
||||
}
|
||||
//for (i=0;i<CP_NSYMB(ue_dl.cell.cp);i++) {
|
||||
// plot_waterfall_appendNewData(&poutfft, &tmp_plot[i*RE_X_RB*ue_dl.cell.nof_prb], RE_X_RB*ue_dl.cell.nof_prb);
|
||||
//}
|
||||
plot_real_setNewData(&pce, tmp_plot2, REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0));
|
||||
if (!prog_args.input_file_name) {
|
||||
int max = vec_max_fi(ue_sync.strack.pss.conv_output_avg, ue_sync.strack.pss.frame_size+ue_sync.strack.pss.fft_size-1);
|
||||
|
@ -533,6 +537,17 @@ void *plot_thread_run(void *arg) {
|
|||
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.pdsch_d, nof_symbols);
|
||||
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.pdcch_d, 36*ue_dl.pdcch.nof_cce);
|
||||
|
||||
if (plot_sf_idx == 1) {
|
||||
if (prog_args.net_port_signal > 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");
|
||||
|
|
|
@ -34,17 +34,20 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;l<refsignal_cs_nof_symbols(port_id);l++) {
|
||||
/* Filter in time domain. */
|
||||
if (q->filter_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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue