Improved synch. Fixed some bugs. Added ue_ul

This commit is contained in:
ismagom 2015-03-05 17:36:15 +00:00
parent 99df252279
commit 6fe535f8a4
29 changed files with 711 additions and 351 deletions

View File

@ -62,29 +62,12 @@ LIBLTE_API double cuhd_set_rx_freq(void *h,
double freq);
LIBLTE_API double cuhd_set_rx_freq_offset(void *h,
double freq,
double off);
LIBLTE_API void cuhd_get_time(void *h,
time_t *secs,
double *frac_secs);
LIBLTE_API double cuhd_set_tx_srate(void *h,
double freq);
LIBLTE_API void cuhd_set_tx_antenna(void *h,
char *name);
LIBLTE_API double cuhd_set_tx_gain(void *h,
double gain);
LIBLTE_API double cuhd_set_tx_freq(void *h,
double freq);
LIBLTE_API double cuhd_set_tx_freq_offset(void *h,
double freq,
double freq,
double off);
LIBLTE_API double cuhd_set_rx_freq_offset(void *h,
double freq,
double off);
LIBLTE_API int cuhd_recv(void *h,
void *data,
@ -94,22 +77,28 @@ LIBLTE_API int cuhd_recv(void *h,
LIBLTE_API int cuhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs);
LIBLTE_API int cuhd_recv_timed(void *h,
void *data,
uint32_t nsamples,
time_t secs,
double frac_secs);
LIBLTE_API double cuhd_set_tx_srate(void *h,
double freq);
LIBLTE_API double cuhd_set_tx_gain(void *h,
double gain);
LIBLTE_API double cuhd_set_tx_freq(void *h,
double freq);
LIBLTE_API double cuhd_set_tx_freq_offset(void *h,
double freq,
double offset);
LIBLTE_API int cuhd_send(void *h,
void *data,
uint32_t nsamples,
bool blocking);
LIBLTE_API int cuhd_recv_timed2(void *h,
void *data,
uint32_t nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst);
LIBLTE_API int cuhd_send(void *h,
void *data,
@ -131,7 +120,6 @@ LIBLTE_API int cuhd_send_timed2(void *h,
bool is_start_of_burst,
bool is_end_of_burst);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -121,8 +121,9 @@ int cuhd_open(char *args, void **h)
{
cuhd_handler *handler = new cuhd_handler();
std::string _args = std::string(args);
handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000");
// "num_recv_frames=1,num_send_frames=1,recv_frame_size=15360,send_frame_size=15360");
handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000" + ", num_recv_frames=512");
// 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
@ -133,7 +134,6 @@ int cuhd_open(char *args, void **h)
otw = "sc16";
cpu = "fc32";
uhd::stream_args_t stream_args(cpu, otw);
stream_args.args["spp"] = "120"; // Set the property
handler->rx_stream = handler->usrp->get_rx_stream(stream_args);
handler->tx_stream = handler->usrp->get_tx_stream(stream_args);
@ -154,15 +154,7 @@ double cuhd_set_rx_srate(void *h, double freq)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_rx_rate(freq);
double ret = handler->usrp->get_rx_rate();
/*
if ((int) ret != (int) freq) {
handler->usrp->set_master_clock_rate(freq);
handler->usrp->set_rx_rate(freq);
}
*/
return freq;
return freq;
}
double cuhd_set_rx_gain(void *h, double gain)
@ -179,9 +171,9 @@ double cuhd_set_rx_freq(void *h, double freq)
return freq;
}
double cuhd_set_rx_freq_offset(void *h, double freq, double off) {
double cuhd_set_rx_freq_offset(void *h, double freq, double off) {
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
handler->usrp->set_rx_freq(uhd::tune_request_t(freq,off));
handler->usrp->set_rx_freq(uhd::tune_request_t(freq, off));
return handler->usrp->get_rx_freq();
}
@ -217,59 +209,41 @@ int cuhd_recv(void *h, void *data, uint32_t nsamples, bool blocking)
int cuhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs)
{
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
uhd::rx_metadata_t md;
int p = handler->rx_stream->recv(data, nsamples, md, 0.0);
uint32_t nof_packets = 0;
int ret = -1;
if (blocking) {
int n = 0, p;
complex_t *data_c = (complex_t *) data;
do {
p = handler->rx_stream->recv(&data_c[n], nsamples - n, md);
if (p == -1) {
return -1;
}
n += p;
#ifdef METADATA_VERBOSE
if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
std::cout << "\nError code: " << md.to_pp_string() << "\n\n";
}
#endif
nof_packets++;
} while (n < nsamples &&
md.error_code == uhd::rx_metadata_t::ERROR_CODE_NONE &&
nof_packets < 10);
ret = nsamples;
} else {
ret = handler->rx_stream->recv(data, nsamples, md, 0.0);
}
if (secs && frac_secs) {
*secs = md.time_spec.get_full_secs();
*frac_secs = md.time_spec.get_frac_secs();
}
return p;
}
int cuhd_recv_timed(void *h,
void *data,
uint32_t nsamples,
time_t secs,
double frac_secs)
{
return cuhd_recv_timed2(h, data, nsamples, secs, frac_secs, true, true);
}
int cuhd_recv_timed2(void *h,
void *data,
uint32_t nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst)
{
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
uhd::rx_metadata_t md;
md.start_of_burst = is_start_of_burst;
md.end_of_burst = is_end_of_burst;
md.has_time_spec = true;
md.time_spec = uhd::time_spec_t(secs, frac_secs);
return handler->rx_stream->recv(data, nsamples, md);
}
void cuhd_get_time(void *h, time_t *secs, double *frac_secs)
{
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
uhd::time_spec_t now = handler->usrp->get_time_now();
*secs = now.get_full_secs();
*frac_secs = now.get_frac_secs();
}
void cuhd_set_tx_antenna(void *h, char *name)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_tx_antenna(name, 0);
return ret;
}
double cuhd_set_tx_gain(void *h, double gain)
{
@ -292,7 +266,8 @@ double cuhd_set_tx_freq(void *h, double freq)
return handler->usrp->get_tx_freq();
}
double cuhd_set_tx_freq_offset(void *h, double freq, double off) {
double cuhd_set_tx_freq_offset(void *h, double freq, double off) {
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
handler->usrp->set_tx_freq(uhd::tune_request_t(freq, off));
return handler->usrp->get_tx_freq();
@ -319,6 +294,7 @@ int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking)
}
}
int cuhd_send_timed(void *h,
void *data,
int nsamples,

View File

@ -125,8 +125,6 @@ int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, timestamp_t *q) {
return cuhd_recv(h, data, nsamples, 1);
}
extern float mean_exec_time;
enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
#define MAX_SINFO 10
@ -261,15 +259,15 @@ int main(int argc, char **argv) {
case DECODE_SIB:
/* We are looking for SI Blocks, search only in appropiate places */
if ((ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
n = ue_dl_decode_sib(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), SIRNTI,
n = ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), SIRNTI,
((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
return -1;
} else if (n == 0) {
printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, ExecTime: %5.1f us, NOI: %.2f, PDCCH-Det: %.3f\r",
printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, NOI: %.2f, PDCCH-Det: %.3f\r",
ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000,
mean_exec_time, sch_average_noi(&ue_dl.pdsch.dl_sch),
sch_average_noi(&ue_dl.pdsch.dl_sch),
(float) ue_dl.nof_pdcch_detected/nof_trials);
nof_trials++;
} else {

View File

@ -83,6 +83,7 @@ typedef struct {
uint32_t file_nof_prb;
char *uhd_args;
float uhd_freq;
float uhd_freq_offset;
float uhd_gain;
int net_port;
char *net_address;
@ -98,6 +99,7 @@ void args_default(prog_args_t *args) {
args->file_nof_prb = 6;
args->uhd_args = "";
args->uhd_freq = -1.0;
args->uhd_freq = 8000000.0;
args->uhd_gain = 60.0;
args->net_port = -1;
args->net_address = "127.0.0.1";
@ -110,6 +112,7 @@ void usage(prog_args_t *args, char *prog) {
#ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain);
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
@ -133,7 +136,7 @@ void usage(prog_args_t *args, char *prog) {
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "aglipdnvrfuUsS")) != -1) {
while ((opt = getopt(argc, argv, "aoglipdnvrfuUsS")) != -1) {
switch (opt) {
case 'i':
args->input_file_name = argv[optind];
@ -147,6 +150,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'g':
args->uhd_gain = atof(argv[optind]);
break;
case 'o':
args->uhd_freq_offset = atof(argv[optind]);
break;
case 'f':
args->uhd_freq = atof(argv[optind]);
break;
@ -261,7 +267,7 @@ int main(int argc, char **argv) {
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
/* set receiver frequency */
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq);
cuhd_set_rx_freq_offset(uhd, (double) prog_args.uhd_freq, prog_args.uhd_freq_offset);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
@ -394,7 +400,7 @@ int main(int argc, char **argv) {
if (prog_args.rnti != SIRNTI) {
n = ue_dl_decode(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync));
} else {
n = ue_dl_decode_sib(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync), SIRNTI,
n = ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync), SIRNTI,
((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
}
if (n < 0) {

View File

@ -151,7 +151,7 @@ void sig_int_handler(int signo)
int cuhd_recv_wrapper_timed(void *h, void *data, uint32_t nsamples, timestamp_t *uhd_time) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv_with_time(h, data, nsamples, &uhd_time->full_secs, &uhd_time->frac_secs);
return cuhd_recv_with_time(h, data, nsamples, true, &uhd_time->full_secs, &uhd_time->frac_secs);
}
extern float mean_exec_time;
@ -314,7 +314,7 @@ int main(int argc, char **argv) {
uint32_t rar_window_start = 0, rar_trials = 0, rar_window_stop = 0;
timestamp_t uhd_time;
timestamp_t next_tx_time;
const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6};
const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00};
uint8_t data[100];
parse_args(&prog_args, argc, argv);
@ -327,7 +327,7 @@ int main(int argc, char **argv) {
/* Set receiver gain */
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
cuhd_set_tx_gain(uhd, prog_args.uhd_gain);
cuhd_set_tx_gain(uhd, prog_args.uhd_gain*2);
//cuhd_set_tx_antenna(uhd, "TX/RX");
@ -336,7 +336,6 @@ int main(int argc, char **argv) {
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning RX receiver to %.3f MHz\n", (double ) prog_args.uhd_rx_freq/1000000);
cuhd_set_tx_freq(uhd, prog_args.uhd_tx_freq);
cuhd_set_tx_freq_offset(uhd, prog_args.uhd_tx_freq, prog_args.uhd_tx_freq_offset);
printf("Tunning TX receiver to %.3f MHz\n", (double ) prog_args.uhd_tx_freq/1000000);
@ -383,24 +382,15 @@ int main(int argc, char **argv) {
generate_prach_sequences();
refsignal_ul_t drms;
refsignal_drms_pusch_cfg_t pusch_cfg;
bzero(&pusch_cfg, sizeof(refsignal_drms_pusch_cfg_t));
pusch_cfg.nof_prb = 3;
pusch_cfg.beta_pusch = 1.0;
if (refsignal_ul_init(&drms, cell)) {
fprintf(stderr, "Error initiating refsignal_ul\n");
exit(-1);
}
cf_t *drms_signal = vec_malloc(2*RE_X_RB*pusch_cfg.nof_prb*sizeof(cf_t));
cf_t *drms_signal = vec_malloc(2*RE_X_RB*cell.nof_prb*sizeof(cf_t));
if (!drms_signal) {
perror("malloc");
exit(-1);
}
for (uint32_t i=0;i<2;i++) {
if (refsignal_dmrs_pusch_gen(&drms, &pusch_cfg, 2*4+i, &drms_signal[i*RE_X_RB*pusch_cfg.nof_prb])) {
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
}
}
if (pusch_init(&pusch, cell)) {
fprintf(stderr, "Error initiating PUSCH\n");
@ -438,7 +428,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (ue_dl_init(&ue_dl, cell)) { // This is the User RNTI
if (ue_dl_init(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
@ -503,7 +493,7 @@ int main(int argc, char **argv) {
if ((sfn == rar_window_start && ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) {
gettimeofday(&tdata[1], NULL);
printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, ue_sync_get_sfidx(&ue_sync));
n = ue_dl_decode_rnti(&ue_dl, sf_buffer, data_rx, ra_rnti, ue_sync_get_sfidx(&ue_sync));
n = ue_dl_decode_rnti(&ue_dl, sf_buffer, data_rx, ue_sync_get_sfidx(&ue_sync), ra_rnti);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
@ -522,7 +512,8 @@ int main(int argc, char **argv) {
ra_ul_alloc(&prb_alloc, &ra_pusch, 0, cell.nof_prb);
if (harq_setup_ul(&pusch_harq, ra_pusch.mcs, 0, (ue_sync_get_sfidx(&ue_sync)+6)%10, &prb_alloc)) {
uint32_t ul_sf_idx = (ue_sync_get_sfidx(&ue_sync)+6)%10;
if (harq_setup_ul(&pusch_harq, ra_pusch.mcs, 0, ul_sf_idx, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
exit(-1);;
}
@ -532,12 +523,28 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
refsignal_drms_pusch_cfg_t pusch_cfg;
bzero(&pusch_cfg, sizeof(refsignal_drms_pusch_cfg_t));
pusch_cfg.nof_prb = prb_alloc.L_prb;
pusch_cfg.beta_pusch = 1.0;
for (uint32_t i=0;i<2;i++) {
refsignal_drms_pusch_put(&drms, &pusch_cfg, &drms_signal[i*RE_X_RB*pusch_cfg.nof_prb], i, prb_alloc.n_prb[i], sf_symbols);
if (refsignal_dmrs_pusch_gen(&drms, &pusch_cfg, 2*ul_sf_idx+i, drms_signal)) {
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
exit(-1);
}
refsignal_drms_pusch_put(&drms, &pusch_cfg, drms_signal, i,
prb_alloc.n_prb[i], sf_symbols);
}
lte_ifft_run_sf(&fft, sf_symbols, ul_signal);
cfo_correct(&ue_sync.sfind.cfocorr,
ul_signal, ul_signal,
sync_get_cfo(&ue_sync.strack) / lte_symbol_sz(cell.nof_prb));
gettimeofday(&tdata[2], NULL);
get_time_interval(tdata);
printf("time exec UL: %d\n",tdata[0].tv_usec);
@ -551,16 +558,16 @@ int main(int argc, char **argv) {
ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31 - 25) * 16 /(15000*2048);
//float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31 - 25) * 16 /(15000*2048);
float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31) * 16 /(15000*2048);
vec_sc_prod_cfc(ul_signal, 2, ul_signal, SF_LEN_PRB(cell.nof_prb));
vec_fprint_c(stdout, sf_symbols, 300);
timestamp_copy(&next_tx_time, &uhd_time);
timestamp_add(&next_tx_time, 0, 0.006 + time_adv_sec); // send after 6 sub-frames (6 ms)
printf("Send %d samples PUSCH sfn: %d. Last frame time = %.6f, send PUSCH time = %.6f TA: %f\n",
SF_LEN_PRB(cell.nof_prb), sfn, timestamp_real(&uhd_time), timestamp_real(&next_tx_time), time_adv_sec);
printf("Send %d samples PUSCH sfn: %d. Last frame time = %.6f"
"send PUSCH time = %.6f TA: %.1f us\n",
SF_LEN_PRB(cell.nof_prb), sfn, timestamp_real(&uhd_time),
timestamp_real(&next_tx_time), time_adv_sec*1000000);
cuhd_send_timed(uhd, ul_signal, SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
@ -569,7 +576,7 @@ int main(int argc, char **argv) {
if (sfn >= rar_window_stop) {
state = SEND_PRACH;
rar_trials++;
if (rar_trials >= 10) {
if (rar_trials >= 4) {
go_exit = 1;
}
}

View File

@ -66,7 +66,8 @@ typedef struct {
cf_t *tmp_noise;
cf_t *tmp_freqavg;
cf_t *tmp_timeavg[CHEST_MAX_FILTER_TIME_LEN];
cf_t *tmp_timeavg_mult;
interp_linvec_t interp_linvec;
interp_lin_t interp_lin;

View File

@ -119,12 +119,13 @@ typedef enum {CPNORM, CPEXT} lte_cp_t;
typedef _Complex float cf_t;
typedef enum LIBLTE_API { PHICH_NORM, PHICH_EXT} phich_length_t;
typedef enum LIBLTE_API { R_1_6, R_1_2, R_1, R_2} phich_resources_t;
typedef enum LIBLTE_API { PHICH_NORM = 0, PHICH_EXT} phich_length_t;
typedef enum LIBLTE_API { R_1_6 = 0, R_1_2, R_1, R_2} phich_resources_t;
typedef struct LIBLTE_API {
uint32_t nof_prb;
uint32_t nof_ports;
uint32_t bw_idx;
uint32_t id;
lte_cp_t cp;
phich_length_t phich_length;

View File

@ -80,14 +80,11 @@ LIBLTE_API int dci_msg_to_ra_dl(dci_msg_t *msg,
uint32_t cfi,
ra_pdsch_t *ra_dl);
/* TODO
LIBLTE_API int dci_msg_to_ra_ul(dci_msg_t *msg,
uint16_t msg_rnti,
uint16_t c_rnti,
lte_cell_t cell,
uint32_t cfi,
uint32_t n_rb_ho,
ra_pusch_t *ra_ul);
*/
LIBLTE_API dci_format_t dci_format_from_string(char *str);
LIBLTE_API char* dci_format_string(dci_format_t format);

View File

@ -51,8 +51,6 @@ typedef struct LIBLTE_API {
ra_ul_alloc_t ul_alloc;
lte_cell_t cell;
ra_ul_hopping_t ul_hopping;
uint32_t nof_re; // Number of RE per subframe
uint32_t nof_bits; // Number of bits per subframe
uint32_t nof_symb; // Number of symbols per subframe

View File

@ -45,9 +45,23 @@
typedef _Complex float cf_t;
typedef struct {
enum {
hop_mode_inter_sf = 1,
hop_mode_intra_sf = 0
} hop_mode;
uint32_t current_tx_nb;
uint32_t hopping_offset;
uint32_t n_sb;
} pusch_hopping_cfg_t;
/* PUSCH object */
typedef struct LIBLTE_API {
lte_cell_t cell;
pusch_hopping_cfg_t hopping_cfg;
uint32_t max_re;
bool rnti_is_set;
@ -77,13 +91,14 @@ typedef struct LIBLTE_API {
}pusch_t;
LIBLTE_API int pusch_init(pusch_t *q,
lte_cell_t cell);
LIBLTE_API void pusch_free(pusch_t *q);
LIBLTE_API void pusch_set_hopping_cfg(pusch_t *q,
pusch_hopping_cfg_t *cfg);
LIBLTE_API int pusch_set_rnti(pusch_t *q,
uint16_t rnti);

View File

@ -84,20 +84,11 @@ typedef struct LIBLTE_API {
typedef struct LIBLTE_API {
uint32_t n_prb[2];
uint32_t n_prb_tilde[2];
uint32_t L_prb;
uint32_t freq_hopping;
} ra_ul_alloc_t;
typedef struct {
enum {
hop_mode_inter_sf = 1,
hop_mode_intra_sf = 0
} hop_mode;
uint32_t current_tx_nb;
uint32_t hopping_offset;
uint32_t n_sb;
} ra_ul_hopping_t;
typedef struct LIBLTE_API {
uint16_t rnti;
ra_type_t alloc_type;

View File

@ -108,6 +108,7 @@
#include "liblte/phy/ue/ue_mib.h"
#include "liblte/phy/ue/ue_cell_search.h"
#include "liblte/phy/ue/ue_dl.h"
#include "liblte/phy/ue/ue_ul.h"
#include "liblte/phy/scrambling/scrambling.h"

View File

@ -41,7 +41,6 @@
#include "liblte/phy/common/phy_common.h"
#include "liblte/phy/phch/dci.h"
#include "liblte/phy/phch/pbch.h"
#include "liblte/phy/phch/pcfich.h"
#include "liblte/phy/phch/pdcch.h"
#include "liblte/phy/phch/pdsch.h"
@ -57,7 +56,6 @@
#define NOF_HARQ_PROCESSES 8
typedef struct LIBLTE_API {
pbch_t pbch;
pcfich_t pcfich;
pdcch_t pdcch;
pdsch_t pdsch;
@ -66,6 +64,8 @@ typedef struct LIBLTE_API {
lte_fft_t fft;
chest_dl_t chest;
ra_pdsch_t ra_dl;
lte_cell_t cell;
cf_t *sf_symbols;
@ -84,6 +84,25 @@ LIBLTE_API int ue_dl_init(ue_dl_t *q,
LIBLTE_API void ue_dl_free(ue_dl_t *q);
LIBLTE_API int ue_dl_decode_fft_estimate(ue_dl_t *q,
cf_t *input,
uint32_t sf_idx,
uint32_t *cfi);
LIBLTE_API int ue_dl_decode_rnti_rv_packet(ue_dl_t *q,
dci_msg_t *dci_msg,
uint8_t *data,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
uint32_t rvidx);
LIBLTE_API int ue_dl_find_ul_dci(ue_dl_t *q,
dci_msg_t *dci_msg,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti);
LIBLTE_API int ue_dl_decode(ue_dl_t * q,
cf_t *input,
uint8_t *data,
@ -92,15 +111,15 @@ LIBLTE_API int ue_dl_decode(ue_dl_t * q,
LIBLTE_API int ue_dl_decode_rnti(ue_dl_t * q,
cf_t *input,
uint8_t *data,
uint16_t rnti,
uint32_t sf_idx);
uint32_t sf_idx,
uint16_t rnti);
LIBLTE_API int ue_dl_decode_sib(ue_dl_t * q,
cf_t *input,
uint8_t * data,
uint32_t sf_idx,
uint16_t rnti,
uint32_t rvidx);
LIBLTE_API int ue_dl_decode_rnti_rv(ue_dl_t * q,
cf_t *input,
uint8_t * data,
uint32_t sf_idx,
uint16_t rnti,
uint32_t rvidx);
LIBLTE_API void ue_dl_reset(ue_dl_t *q);

View File

@ -0,0 +1,114 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef UEUL_H
#define UEUL_H
/*******************************************************
*
* This module is a frontend to all the data and control channels processing
* modules.
********************************************************/
#include "liblte/phy/ch_estimation/chest_dl.h"
#include "liblte/phy/common/fft.h"
#include "liblte/phy/common/phy_common.h"
#include "liblte/phy/ch_estimation/refsignal_ul.h"
#include "liblte/phy/phch/pusch.h"
#include "liblte/phy/phch/ra.h"
#include "liblte/phy/sync/cfo.h"
#include "liblte/phy/utils/vector.h"
#include "liblte/phy/utils/debug.h"
#include "liblte/config.h"
#define NOF_HARQ_PROCESSES 8
typedef struct LIBLTE_API {
lte_fft_t fft;
cfo_t cfo;
lte_cell_t cell;
float current_cfo;
refsignal_drms_pusch_cfg_t pusch_drms_cfg;
refsignal_ul_t drms;
harq_t harq_process[NOF_HARQ_PROCESSES];
pusch_t pusch;
cf_t *refsignal;
cf_t *sf_symbols;
uint16_t current_rnti;
}ue_ul_t;
/* This function shall be called just after the initial synchronization */
LIBLTE_API int ue_ul_init(ue_ul_t *q,
lte_cell_t cell);
LIBLTE_API void ue_ul_free(ue_ul_t *q);
LIBLTE_API void ue_ul_set_cfo(ue_ul_t *q,
float cur_cfo);
LIBLTE_API void ue_ul_set_pusch_cfg(ue_ul_t *q,
refsignal_drms_pusch_cfg_t *pusch_drms_cfg,
pusch_hopping_cfg_t *pusch_hopping_cfg);
LIBLTE_API int ue_ul_pusch_encode(ue_ul_t *q,
ra_pusch_t *ra_ul,
uint8_t *data,
cf_t *output_signal);
LIBLTE_API int ue_ul_pusch_encode_rnti(ue_ul_t *q,
ra_pusch_t *ra_ul,
uint8_t *data,
uint16_t rnti,
cf_t *output_signal);
LIBLTE_API int ue_ul_pusch_uci_encode(ue_ul_t *q,
ra_pusch_t *ra_ul,
uint8_t *data,
uci_data_t uci_data,
cf_t *output_signal);
LIBLTE_API int ue_ul_pusch_uci_encode_rnti(ue_ul_t *q,
ra_pusch_t *ra_ul,
uint8_t *data,
uci_data_t uci_data,
uint16_t rnti,
cf_t *output_signal);
LIBLTE_API void ue_ul_reset(ue_ul_t *q);
LIBLTE_API void ue_ul_set_rnti(ue_ul_t *q,
uint16_t rnti);
#endif

View File

@ -87,6 +87,12 @@ int chest_dl_init(chest_dl_t *q, lte_cell_t cell)
}
bzero(q->tmp_timeavg[i], sizeof(cf_t) * 2*cell.nof_prb);
}
q->tmp_timeavg_mult = vec_malloc(sizeof(cf_t) * 2*cell.nof_prb);
if (!q->tmp_timeavg_mult) {
perror("malloc");
goto clean_exit;
}
bzero(q->tmp_timeavg_mult, sizeof(cf_t) * 2*cell.nof_prb);
for (int i=0;i<cell.nof_ports;i++) {
q->pilot_estimates[i] = vec_malloc(sizeof(cf_t) * REFSIGNAL_NUM_SF(cell.nof_prb, i));
@ -117,14 +123,14 @@ int chest_dl_init(chest_dl_t *q, lte_cell_t cell)
}
/* Set default time/freq filters */
float f[3]={0.15, 0.7, 0.15};
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.2, 0.5, 0.2, 0.05};
chest_dl_set_filter_freq(q, f, 5);
float t[2]={0.2, 0.8};
chest_dl_set_filter_time(q, t, 2);
chest_dl_set_filter_time(q, t, 0);
q->cell = cell;
}
@ -153,6 +159,9 @@ void chest_dl_free(chest_dl_t *q)
free(q->tmp_timeavg[i]);
}
}
if (q->tmp_timeavg_mult) {
free(q->tmp_timeavg_mult);
}
interp_linear_vector_free(&q->interp_linvec);
interp_linear_free(&q->interp_lin);
@ -239,10 +248,11 @@ static void average_pilots(chest_dl_t *q, uint32_t port_id)
conv_same_cf(&pilot_est(0), q->filter_freq, &pilot_tmp(0), nref, q->filter_freq_len);
/* Adjust extremes using linear interpolation */
pilot_tmp(0) += interp_linear_onesample(pilot_est(1), pilot_est(0))
* q->filter_freq[q->filter_freq_len/2-1];
* q->filter_freq[q->filter_freq_len/2-1]*1.2;
pilot_tmp(nref-1) += interp_linear_onesample(pilot_est(nref-2), pilot_est(nref-1))
* q->filter_freq[q->filter_freq_len/2+1];
* q->filter_freq[q->filter_freq_len/2+1]*1.2;
} else {
memcpy(&pilot_tmp(0), &pilot_est(0), nref * sizeof(cf_t));
}

View File

@ -243,7 +243,11 @@ bool refsignal_drms_pusch_cfg_isvalid(refsignal_ul_t *q, refsignal_drms_pusch_cf
}
}
void refsignal_drms_pusch_put(refsignal_ul_t *q, refsignal_drms_pusch_cfg_t *cfg, cf_t *r_pusch, uint32_t ns_idx, uint32_t n_prb, cf_t *sf_symbols) {
void refsignal_drms_pusch_put(refsignal_ul_t *q, refsignal_drms_pusch_cfg_t *cfg,
cf_t *r_pusch,
uint32_t ns_idx, uint32_t n_prb,
cf_t *sf_symbols)
{
if (ns_idx < 2) {
uint32_t L = (ns_idx+1)*CP_NSYMB(q->cell.cp)-4;
memcpy(&sf_symbols[RE_IDX(q->cell.nof_prb, L, n_prb*RE_X_RB)], r_pusch, cfg->nof_prb*RE_X_RB*sizeof(cf_t));

View File

@ -97,6 +97,37 @@ int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti,
return ret;
}
int dci_msg_to_ra_ul(dci_msg_t *msg, lte_cell_t cell, uint32_t n_rb_ho, ra_pusch_t *ra_ul)
{
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (msg != NULL &&
ra_ul != NULL &&
lte_cell_isvalid(&cell))
{
ret = LIBLTE_ERROR;
bzero(ra_ul, sizeof(ra_pusch_t));
if (dci_msg_unpack_pusch(msg, ra_ul, cell.nof_prb)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
return ret;
}
if (VERBOSE_ISINFO()) {
ra_pusch_fprint(stdout, ra_ul, cell.nof_prb);
}
if (ra_ul_alloc(&ra_ul->prb_alloc, ra_ul, n_rb_ho, cell.nof_prb)) {
fprintf(stderr, "Error computing resource allocation\n");
return ret;
}
ret = LIBLTE_SUCCESS;
}
return ret;
}
int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) {
if (L <= 3) {
c->L = L;

View File

@ -106,13 +106,13 @@ int harq_init(harq_t *q, lte_cell_t cell) {
if (ret != LIBLTE_ERROR) {
q->max_cb = (uint32_t) ret / (MAX_LONG_CB - 24) + 1;
q->pdsch_w_buff_f = malloc(sizeof(float*) * q->max_cb);
q->pdsch_w_buff_f = vec_malloc(sizeof(float*) * q->max_cb);
if (!q->pdsch_w_buff_f) {
perror("malloc");
return LIBLTE_ERROR;
}
q->pdsch_w_buff_c = malloc(sizeof(uint8_t*) * q->max_cb);
q->pdsch_w_buff_c = vec_malloc(sizeof(uint8_t*) * q->max_cb);
if (!q->pdsch_w_buff_c) {
perror("malloc");
return LIBLTE_ERROR;

View File

@ -42,9 +42,10 @@
#include "liblte/phy/utils/debug.h"
const uint8_t crc_mask[4][16] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0 }, { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 } };
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 } };
bool pbch_exists(int nframe, int nslot) {
return (!(nframe % 5) && nslot == 1);
@ -246,10 +247,10 @@ void pbch_free(pbch_t *q) {
* msg buffer must be 24 byte length at least
*/
void pbch_mib_unpack(uint8_t *msg, lte_cell_t *cell, uint32_t *sfn) {
int bw, phich_res;
int phich_res;
bw = bit_unpack(&msg, 3);
switch (bw) {
cell->bw_idx = bit_unpack(&msg, 3);
switch (cell->bw_idx) {
case 0:
cell->nof_prb = 6;
break;
@ -257,7 +258,7 @@ void pbch_mib_unpack(uint8_t *msg, lte_cell_t *cell, uint32_t *sfn) {
cell->nof_prb = 15;
break;
default:
cell->nof_prb = (bw - 1) * 25;
cell->nof_prb = (cell->bw_idx - 1) * 25;
break;
}
if (*msg) {

View File

@ -57,7 +57,7 @@ static int f_hop_sum(pusch_t *q, uint32_t i) {
return sum;
}
static int f_hop(pusch_t *q, ra_ul_hopping_t *hopping, int i) {
static int f_hop(pusch_t *q, pusch_hopping_cfg_t *hopping, int i) {
if (i == -1) {
return 0;
} else {
@ -71,7 +71,7 @@ static int f_hop(pusch_t *q, ra_ul_hopping_t *hopping, int i) {
}
}
static int f_m(pusch_t *q, ra_ul_hopping_t *hopping, uint32_t i) {
static int f_m(pusch_t *q, pusch_hopping_cfg_t *hopping, uint32_t i) {
if (hopping->n_sb == 1) {
if (hopping->hop_mode == hop_mode_inter_sf) {
return hopping->current_tx_nb%2;
@ -87,7 +87,7 @@ int pusch_cp(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output, bool advance_i
{
cf_t *in_ptr = input;
cf_t *out_ptr = output;
ra_ul_hopping_t *hopping = &harq->ul_hopping;
pusch_hopping_cfg_t *hopping = &q->hopping_cfg;
uint32_t L_ref = 3;
if (CP_ISEXT(q->cell.cp)) {
@ -128,6 +128,7 @@ int pusch_cp(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output, bool advance_i
}
}
harq->ul_alloc.n_prb_tilde[slot] = n_prb_tilde;
INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",harq->ul_alloc.L_prb, n_prb_tilde,slot);
for (uint32_t l=0;l<CP_NSYMB(q->cell.cp);l++) {
if (l != L_ref) {
@ -278,6 +279,11 @@ void pusch_free(pusch_t *q) {
}
void pusch_set_hopping_cfg(pusch_t *q, pusch_hopping_cfg_t *cfg)
{
memcpy(&q->hopping_cfg, cfg, sizeof(pusch_hopping_cfg_t));
}
/* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
* For the connection procedure, use pusch_encode_rnti() or pusch_decode_rnti() functions */
@ -412,9 +418,6 @@ int pusch_uci_encode_rnti(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uc
return LIBLTE_ERROR;
}
printf("before scram: ");
vec_fprint_b(stdout, q->pusch_q, harq->nof_bits);
if (rnti != q->rnti) {
sequence_t seq;
if (sequence_pusch(&seq, rnti, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
@ -426,9 +429,6 @@ int pusch_uci_encode_rnti(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uc
scrambling_b_offset_pusch(&q->seq_pusch[harq->sf_idx], (uint8_t*) q->pusch_q, 0, harq->nof_bits);
}
printf("after scram: ");
vec_fprint_b(stdout, q->pusch_q, harq->nof_bits);
mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, harq->nof_bits);
dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z,

View File

@ -191,10 +191,13 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
harq_process.ul_hopping.n_sb = 1;
harq_process.ul_hopping.hopping_offset = 0;
harq_process.ul_hopping.hop_mode = hop_mode_inter_sf;
harq_process.ul_hopping.current_tx_nb = 0;
pusch_hopping_cfg_t ul_hopping;
ul_hopping.n_sb = 1;
ul_hopping.hopping_offset = 0;
ul_hopping.hop_mode = hop_mode_inter_sf;
ul_hopping.current_tx_nb = 0;
pusch_set_hopping_cfg(&pusch, &ul_hopping);
uint32_t nof_re = RE_X_RB*cell.nof_prb*2*CP_NSYMB(cell.cp);
sf_symbols = vec_malloc(sizeof(cf_t) * nof_re);

View File

@ -37,14 +37,7 @@
/*************** STATIC FUNCTIONS ***********************/
cf_t interp_linear_onesample(cf_t input0, cf_t input1) {
float mag0=0, mag1=0, arg0=0, arg1=0, mag=0, arg=0;
mag0 = cabsf(input0);
mag1 = cabsf(input1);
arg0 = cargf(input0);
arg1 = cargf(input1);
mag = 2*mag1 -mag0;
arg = 2*arg1-arg0;
return mag * cexpf(I * arg);
return 2*input1-input0;
}
cf_t interp_linear_onesample_cabs(cf_t input0, cf_t input1) {

View File

@ -149,15 +149,7 @@ int sss_synch_N_id_1(sss_synch_t *q, uint32_t m0, uint32_t m1) {
} else {
N_id_1 = q->N_id_1_table[m1][m0 - 1];
}
if (N_id_1 == 0) {
if (m0 == 0 && m1 == 1) {
return N_id_1;
} else {
return LIBLTE_ERROR;
}
} else {
return N_id_1;
}
return N_id_1;
}
/** High-level API */

View File

@ -194,6 +194,7 @@ int main(int argc, char **argv) {
frame_cnt = 0;
last_peak = 0;
mean_peak = 0;
int peak_offset = 0;
float cfo;
float mean_cfo = 0;
uint32_t m0, m1;
@ -204,27 +205,12 @@ int main(int argc, char **argv) {
bzero(&ssync, sizeof(sync_t));
ssync.fft_size = fft_size;
timestamp_t cur_time;
cuhd_get_time(uhd, &cur_time.full_secs, &cur_time.frac_secs);
// wait 1 sec to start
timestamp_add(&cur_time, 1, 0);
double period = 0.005; // 5 ms
double period_diff = 0;
double nsamples_offset_x_sf;
int last_peak_idx = 0;
bool is_first = true;
while(frame_cnt < nof_frames || nof_frames == -1) {
timestamp_add(&cur_time, 0, period + period_diff);
n = cuhd_recv_timed2(uhd, buffer, flen, cur_time.full_secs, cur_time.frac_secs, is_first, false);
n = cuhd_recv(uhd, buffer, flen - peak_offset, 1);
if (n < 0) {
fprintf(stderr, "Error receiving samples\n");
exit(-1);
}
is_first = false;
peak_idx = pss_synch_find_pss(&pss, buffer, &peak_value);
if (peak_idx < 0) {
@ -236,13 +222,7 @@ int main(int argc, char **argv) {
if (peak_value >= threshold) {
nof_det++;
if (last_peak_idx) {
nsamples_offset_x_sf = VEC_CMA(((double) peak_idx - (double) last_peak_idx ), nsamples_offset_x_sf, frame_cnt);
period_diff += nsamples_offset_x_sf / (flen*2*100);
}
last_peak_idx = peak_idx;
if (peak_idx >= fft_size) {
// Estimate CFO
@ -273,7 +253,7 @@ int main(int argc, char **argv) {
INFO("Diff N_id_1: %d\n", sss_synch_N_id_1(&sss, m0, m1));
sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value);
if (sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
sss_error1++;
sss_error1++;
}
INFO("Full N_id_1: %d\n", sss_synch_N_id_1(&sss, m0, m1));
}
@ -308,10 +288,10 @@ int main(int argc, char **argv) {
frame_cnt++;
printf("[%5d]: Pos: %5d (%f), PSR: %4.1f (~%4.1f) Pdet: %4.2f, "
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, period_diff*1000000,
peak_idx,
peak_value, mean_peak,
(float) nof_det/frame_cnt,
(float) nof_nopeakdet/frame_cnt, mean_cfo*15,
@ -408,4 +388,3 @@ void do_plots_sss(float *corr_m0, float *corr_m1) {
}
#endif

View File

@ -66,10 +66,6 @@ int ue_dl_init(ue_dl_t *q,
fprintf(stderr, "Error initiating REGs\n");
goto clean_exit;
}
if (pbch_init(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n");
goto clean_exit;
}
if (pcfich_init(&q->pcfich, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit;
@ -121,7 +117,6 @@ void ue_dl_free(ue_dl_t *q) {
lte_fft_free(&q->fft);
chest_dl_free(&q->chest);
regs_free(&q->regs);
pbch_free(&q->pbch);
pcfich_free(&q->pcfich);
pdcch_free(&q->pdcch);
pdsch_free(&q->pdsch);
@ -155,8 +150,6 @@ void ue_dl_reset(ue_dl_t *q) {
harq_reset(&q->harq_process[0]);
}
LIBLTE_API float mean_exec_time=0;
dci_format_t ue_formats[] = {Format1,Format1A}; // Format1B should go here also
const uint32_t nof_ue_formats = 2;
@ -171,48 +164,116 @@ const uint32_t nof_common_formats = 2;
* - PDSCH decoding: Decode TB scrambling with RNTI given by ue_dl_set_rnti()
*/
int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx) {
return ue_dl_decode_sib(q, input, data, sf_idx, q->current_rnti, 0);
return ue_dl_decode_rnti_rv(q, input, data, sf_idx, q->current_rnti, 0);
}
int ue_dl_decode_rnti(ue_dl_t *q, cf_t *input, uint8_t *data, uint16_t rnti, uint32_t sf_idx) {
return ue_dl_decode_sib(q, input, data, sf_idx, rnti, 0);
int ue_dl_decode_rnti(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti) {
return ue_dl_decode_rnti_rv(q, input, data, sf_idx, rnti, 0);
}
int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{
uint32_t cfi, i;
int ue_dl_decode_fft_estimate(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) {
float cfi_corr;
ra_pdsch_t ra_dl;
dci_location_t locations[MAX_CANDIDATES];
dci_msg_t dci_msg;
uint32_t nof_locations;
uint16_t crc_rem;
if (input && q && cfi && sf_idx < NSUBFRAMES_X_FRAME) {
/* Run FFT for all subframe data */
lte_fft_run_sf(&q->fft, input, q->sf_symbols);
/* Get channel estimates for each port */
chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx);
/* First decode PCFICH and obtain CFI */
if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce,
chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi, &cfi_corr)<0) {
fprintf(stderr, "Error decoding PCFICH\n");
return LIBLTE_ERROR;
}
INFO("Decoded CFI=%d with correlation %.2f\n", cfi, cfi_corr);
if (regs_set_cfi(&q->regs, *cfi)) {
fprintf(stderr, "Error setting CFI\n");
return LIBLTE_ERROR;
}
/* Extract all PDCCH symbols and get LLRs */
if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), sf_idx, *cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return LIBLTE_ERROR;
}
return LIBLTE_SUCCESS;
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}
}
int ue_dl_decode_rnti_rv_packet(ue_dl_t *q, dci_msg_t *dci_msg, uint8_t *data,
uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{
int ret = LIBLTE_ERROR;
struct timeval t[3];
uint32_t nof_formats;
dci_format_t *formats = NULL;
/* Run FFT for all subframe data */
lte_fft_run_sf(&q->fft, input, q->sf_symbols);
gettimeofday(&t[1], NULL);
/* Get channel estimates for each port */
chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx);
/* First decode PCFICH and obtain CFI */
if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce,
chest_dl_get_noise_estimate(&q->chest), sf_idx, &cfi, &cfi_corr)<0) {
fprintf(stderr, "Error decoding PCFICH\n");
q->nof_pdcch_detected++;
if (dci_msg_to_ra_dl(dci_msg, rnti, q->cell, cfi, &q->ra_dl)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return LIBLTE_ERROR;
}
INFO("Decoded CFI=%d with correlation %.2f\n", cfi, cfi_corr);
if (regs_set_cfi(&q->regs, cfi)) {
fprintf(stderr, "Error setting CFI\n");
if (rnti != SIRNTI) {
rvidx = q->ra_dl.rv_idx;
}
if (harq_setup_dl(&q->harq_process[0], q->ra_dl.mcs, rvidx, sf_idx, &q->ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return LIBLTE_ERROR;
}
if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) {
ret = pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols,
q->ce, chest_dl_get_noise_estimate(&q->chest),
rnti, data);
if (ret == LIBLTE_ERROR) {
q->pkt_errors++;
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling pdsch_decode()\n");
} else if (ret == LIBLTE_SUCCESS) {
if (VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0);
vec_fprint_hex(stdout, data, q->ra_dl.mcs.tbs);
}
}
q->pkts_total++;
}
return ret;
}
int ue_dl_find_ul_dci(ue_dl_t *q, dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti)
{
dci_location_t locations[MAX_CANDIDATES];
uint32_t nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
uint16_t crc_rem = 0;
for (uint32_t i=0;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_decode_msg(&q->pdcch, dci_msg, &locations[i], Format0, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return LIBLTE_ERROR;
}
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
}
return crc_rem == rnti;
}
int ue_dl_decode_rnti_rv(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{
uint32_t cfi, i;
dci_msg_t dci_msg;
dci_location_t locations[MAX_CANDIDATES];
uint32_t nof_locations;
uint16_t crc_rem;
int ret = LIBLTE_ERROR;
uint32_t nof_formats;
dci_format_t *formats = NULL;
if ((ret = ue_dl_decode_fft_estimate(q, input, sf_idx, &cfi)) < 0) {
return ret;
}
/* Generate PDCCH candidates */
if (rnti == SIRNTI) {
@ -225,11 +286,6 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui
nof_formats = nof_ue_formats;
}
/* Extract all PDCCH symbols and get LLRs */
if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return LIBLTE_ERROR;
}
/* For all possible locations, try to decode a DCI message */
crc_rem = 0;
uint32_t found_dci = 0;
@ -242,50 +298,14 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
if (crc_rem == rnti) {
found_dci++;
q->nof_pdcch_detected++;
if (dci_msg_to_ra_dl(&dci_msg, rnti, q->cell, cfi, &ra_dl)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return LIBLTE_ERROR;
}
if (rnti != SIRNTI) {
rvidx = ra_dl.rv_idx;
}
if (harq_setup_dl(&q->harq_process[0], ra_dl.mcs, rvidx, sf_idx, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return LIBLTE_ERROR;
}
if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) {
ret = pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols,
q->ce, chest_dl_get_noise_estimate(&q->chest),
rnti, data);
if (ret == LIBLTE_ERROR) {
q->pkt_errors++;
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling pdsch_decode()\n");
return LIBLTE_ERROR;
} else if (ret == LIBLTE_SUCCESS) {
if (VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0);
vec_fprint_hex(stdout, data, ra_dl.mcs.tbs);
}
}
q->pkts_total++;
}
found_dci++;
ret = ue_dl_decode_rnti_rv_packet(q, &dci_msg, data, cfi, sf_idx, rnti, rvidx);
}
}
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
mean_exec_time = (float) VEC_EMA((float) t[0].tv_usec, mean_exec_time, 0.01);
if (found_dci > 0 && ret == LIBLTE_SUCCESS) {
return ra_dl.mcs.tbs;
return q->ra_dl.mcs.tbs;
} else {
return 0;
}

View File

@ -121,7 +121,7 @@ int ue_mib_decode(ue_mib_t * q, cf_t *input,
/* Run FFT for the slot symbols */
lte_fft_run_sf(&q->fft, input, q->sf_symbols);
/* Get channel estimates of slot #1 for each port */
/* Get channel estimates of sf idx #0 for each port */
ret = chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0);
if (ret < 0) {
return LIBLTE_ERROR;
@ -214,9 +214,7 @@ int ue_mib_sync_decode(ue_mib_sync_t * q,
break;
} else if (ue_sync_get_sfidx(&q->ue_sync) == 0) {
if (ret == 1) {
ue_mib_reset(&q->ue_mib);
mib_ret = ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset);
mib_ret = ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset);
} else {
INFO("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt);
ue_mib_reset(&q->ue_mib);

View File

@ -42,7 +42,7 @@
#define MAX_TIME_OFFSET 128
cf_t dummy[MAX_TIME_OFFSET];
#define TRACK_MAX_LOST 10
#define TRACK_MAX_LOST 4
#define TRACK_FRAME_SIZE 32
#define FIND_NOF_AVG_FRAMES 2
@ -140,7 +140,7 @@ int ue_sync_init(ue_sync_t *q,
sync_set_threshold(&q->sfind, 1.3);
sync_set_em_alpha(&q->sfind, 0.01);
q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES;
sync_set_threshold(&q->strack, 1.2);
sync_set_threshold(&q->strack, 1.0);
} else {
sync_set_N_id_2(&q->sfind, cell.id%3);
@ -155,8 +155,8 @@ int ue_sync_init(ue_sync_t *q,
*/
sync_set_em_alpha(&q->sfind, 1);
q->nof_avg_find_frames = 1;
sync_set_threshold(&q->sfind, 2.0);
sync_set_threshold(&q->strack, 1.2);
sync_set_threshold(&q->sfind, 4.0);
sync_set_threshold(&q->strack, 1.3);
/* Correct CFO in the find state but not in the track state, since is called only
* 1 every 5 subframes. Will do it in the ue_sync_get_buffer() function.
@ -286,33 +286,33 @@ static int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
q->strack.m0, q->strack.m0_value, q->strack.m1, q->strack.m1_value);
q->sf_idx = sync_get_sf_idx(&q->strack);
}
} else {
// Adjust time offset
q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2 - (int) q->strack.fft_size);
if (q->time_offset) {
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("\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, &q->last_timestamp) < 0) {
fprintf(stderr, "Error receiving from USRP\n");
return LIBLTE_ERROR;
}
q->time_offset = 0;
}
q->peak_idx = q->sf_len/2 + q->time_offset;
q->frame_ok_cnt++;
q->frame_no_cnt = 0;
}
// Adjust time offset
q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2 - (int) q->strack.fft_size);
if (q->time_offset) {
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. Mean time offset %f.\n", q->time_offset, q->mean_time_offset);
if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) {
fprintf(stderr, "Error receiving from USRP\n");
return LIBLTE_ERROR;
}
q->time_offset = 0;
}
q->peak_idx = q->sf_len/2 + q->time_offset;
q->frame_ok_cnt++;
q->frame_no_cnt = 0;
return 1;
}
@ -456,6 +456,13 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
-sync_get_cfo(&q->strack) / q->fft_size);
}
/*
if (track_idx > q->fft_size + q->strack.frame_size/2) {
*sf_symbols = &q->input_buffer[track_idx - q->fft_size - q->strack.frame_size/2];
} else {
*sf_symbols = q->input_buffer;
}
*/
*sf_symbols = q->input_buffer;
break;

210
lte/phy/lib/ue/src/ue_ul.c Normal file
View File

@ -0,0 +1,210 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "liblte/phy/ue/ue_ul.h"
#include <complex.h>
#include <math.h>
#define CURRENT_FFTSIZE lte_symbol_sz(q->cell.nof_prb)
#define CURRENT_SFLEN SF_LEN(CURRENT_FFTSIZE, q->cell.cp)
#define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
int ue_ul_init(ue_ul_t *q,
lte_cell_t cell)
{
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
lte_cell_isvalid(&cell))
{
ret = LIBLTE_ERROR;
bzero(q, sizeof(ue_ul_t));
q->cell = cell;
if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
lte_fft_set_freq_shift(&q->fft, 0.5);
if (cfo_init(&q->cfo, CURRENT_SFLEN)) {
fprintf(stderr, "Error creating CFO object\n");
goto clean_exit;
}
if (pusch_init(&q->pusch, q->cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
for (uint32_t i=0;i<NOF_HARQ_PROCESSES; i++) {
if (harq_init(&q->harq_process[i], q->cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
goto clean_exit;
}
}
if (refsignal_ul_init(&q->drms, cell)) {
fprintf(stderr, "Error initiating refsignal_ul\n");
goto clean_exit;
}
q->sf_symbols = vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->refsignal = vec_malloc(RE_X_RB * q->cell.nof_prb * sizeof(cf_t));
if (!q->refsignal) {
perror("malloc");
goto clean_exit;
}
ret = LIBLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
clean_exit:
if (ret == LIBLTE_ERROR) {
ue_ul_free(q);
}
return ret;
}
void ue_ul_free(ue_ul_t *q) {
if (q) {
lte_fft_free(&q->fft);
pusch_free(&q->pusch);
for (uint32_t i=0;i<NOF_HARQ_PROCESSES; i++) {
harq_free(&q->harq_process[i]);
}
cfo_free(&q->cfo);
refsignal_ul_free(&q>drms);
if (q->sf_symbols) {
free(q->sf_symbols);
}
if (q->refsignal) {
free(q->refsignal);
}
bzero(q, sizeof(ue_ul_t));
}
}
void ue_ul_set_cfo(ue_ul_t *q, float cur_cfo) {
q->current_cfo = cur_cfo;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
* For the connection procedure, use pusch_encode_rnti() or pusch_decode_rnti() functions
*/
void ue_ul_set_rnti(ue_ul_t *q, uint16_t rnti) {
q->current_rnti = rnti;
pusch_set_rnti(&q->pusch, rnti);
}
void ue_ul_reset(ue_ul_t *q) {
harq_reset(&q->harq_process[0]);
}
void ue_ul_set_pusch_cfg(ue_ul_t *q, refsignal_drms_pusch_cfg_t *pusch_drms_cfg, pusch_hopping_cfg_t *pusch_hopping_cfg)
{
pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
}
int ue_ul_pusch_encode(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, cf_t *output_signal)
{
uci_data_t uci_data;
bzero(&uci_data, sizeof(uci_data_t));
return ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal);
}
int ue_ul_pusch_encode_rnti(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uint16_t rnti, uint32_t sf_idx, cf_t *output_signal)
{
uci_data_t uci_data;
bzero(&uci_data, sizeof(uci_data_t));
return ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, rnti, output_signal);
}
int ue_ul_pusch_uci_encode(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uci_data_t uci_data, uint32_t sf_idx, cf_t *output_signal)
{
return ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal);
}
int ue_ul_pusch_uci_encode_rnti(ue_ul_t *q, ra_pusch_t *ra_ul, uint8_t *data, uci_data_t uci_data,
uint32_t sf_idx, uint16_t rnti,
cf_t *output_signal)
{
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
ra_ul != NULL &&
data != NULL &&
output_signal != NULL)
{
if (ra_ul->prb_alloc.L_prb == 0) {
fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n" ;
return ret;
}
}
ret = LIBLTE_ERROR;
if (harq_setup_ul(&q->harq_process[0], ra_ul->mcs, ra_ul->rv_idx, sf_idx, &ra_ul->prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return ret;
}
if (pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
return ret;
}
q->pusch_drms_cfg.nof_prb = ra_ul->prb_alloc.L_prb;
for (uint32_t i=0;i<2;i++) {
// FIXME: Pregenerate for all possible number of prb
if (refsignal_dmrs_pusch_gen(&q->drms, &q->pusch_drms_cfg, 2*sf_idx+i, q->refsignal)) {
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret;
}
refsignal_drms_pusch_put(&q->drms, &q->pusch_drms_cfg, q->refsignal, i,
ra_ul->prb_alloc.n_prb_tilde[i], q->sf_symbols);
}
lte_ifft_run_sf(&q->fft, q->sf_symbols, output_signal);
cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / lte_symbol_sz(q->cell.nof_prb));
ret = LIBLTE_SUCCESS;
}

View File

@ -1,6 +1,6 @@
clear
ueConfig=struct('NCellID',0,'NULRB',25,'NSubframe',4,'RNTI',82,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[0 1 2]','Modulation','QPSK','RV',0,'Shortened',0);
ueConfig=struct('NCellID',1,'NULRB',25,'NSubframe',4,'RNTI',82,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[21:24]','Modulation','QPSK','RV',0,'Shortened',0);
addpath('../../debug/lte/phy/lib/phch/test')
@ -10,7 +10,7 @@ addpath('../../debug/lte/phy/lib/phch/test')
% rvs=0;
% betas=0:3:11;
TBs=56;
TBs=88;
cqilen=0;
mods={'QPSK'};
rvs=0;