Fixed PRACH example

master
ismagom 10 years ago
parent d5a0be5e92
commit 99df252279

@ -65,17 +65,9 @@ LIBLTE_API double cuhd_set_rx_freq_offset(void *h,
double freq, double freq,
double off); double off);
LIBLTE_API int cuhd_recv(void *h, LIBLTE_API void cuhd_get_time(void *h,
void *data, time_t *secs,
uint32_t nsamples, double *frac_secs);
bool blocking);
LIBLTE_API int cuhd_recv_timed(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs);
LIBLTE_API double cuhd_set_tx_srate(void *h, LIBLTE_API double cuhd_set_tx_srate(void *h,
double freq); double freq);
@ -93,6 +85,32 @@ LIBLTE_API double cuhd_set_tx_freq_offset(void *h,
double freq, double freq,
double off); double off);
LIBLTE_API int cuhd_recv(void *h,
void *data,
uint32_t nsamples,
bool blocking);
LIBLTE_API int cuhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
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 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, LIBLTE_API int cuhd_send(void *h,
void *data, void *data,
uint32_t nsamples, uint32_t nsamples,
@ -102,10 +120,18 @@ LIBLTE_API int cuhd_send(void *h,
LIBLTE_API int cuhd_send_timed(void *h, LIBLTE_API int cuhd_send_timed(void *h,
void *data, void *data,
int nsamples, int nsamples,
int blocking,
time_t secs, time_t secs,
double frac_secs); double frac_secs);
LIBLTE_API int cuhd_send_timed2(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -156,11 +156,12 @@ double cuhd_set_rx_srate(void *h, double freq)
handler->usrp->set_rx_rate(freq); handler->usrp->set_rx_rate(freq);
double ret = handler->usrp->get_rx_rate(); double ret = handler->usrp->get_rx_rate();
/*
if ((int) ret != (int) freq) { if ((int) ret != (int) freq) {
handler->usrp->set_master_clock_rate(freq); handler->usrp->set_master_clock_rate(freq);
handler->usrp->set_rx_rate(freq); handler->usrp->set_rx_rate(freq);
} }
*/
return freq; return freq;
} }
@ -213,39 +214,56 @@ int cuhd_recv(void *h, void *data, uint32_t nsamples, bool blocking)
} }
} }
int cuhd_recv_timed(void *h, int cuhd_recv_with_time(void *h,
void *data, void *data,
uint32_t nsamples, uint32_t nsamples,
bool blocking, time_t *secs,
time_t *secs, double *frac_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; uhd::rx_metadata_t md;
*secs = -1; int p = handler->rx_stream->recv(data, nsamples, md, 0.0);
*frac_secs = -1; if (secs && frac_secs) {
int p;
if (blocking) {
int n=0;
complex_t *data_c = (complex_t*) data;
do {
p=handler->rx_stream->recv(&data_c[n], nsamples-n, md);
if (p == -1) {
return -1;
}
if(*secs < 0){
*secs = md.time_spec.get_full_secs();
*frac_secs = md.time_spec.get_frac_secs();
}
n+=p;
} while(n<nsamples);
return n;
} else {
p = handler->rx_stream->recv(data, nsamples, md, 0.0);
*secs = md.time_spec.get_full_secs(); *secs = md.time_spec.get_full_secs();
*frac_secs = md.time_spec.get_frac_secs(); *frac_secs = md.time_spec.get_frac_secs();
return p;
} }
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) void cuhd_set_tx_antenna(void *h, char *name)
@ -301,32 +319,28 @@ int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking)
} }
} }
int cuhd_send_timed(void *h, int cuhd_send_timed(void *h,
void *data, void *data,
int nsamples, int nsamples,
int blocking,
time_t secs, time_t secs,
double frac_secs) { double frac_secs)
{
return cuhd_send_timed2(h, data, nsamples, secs, frac_secs, true, true);
}
int cuhd_send_timed2(void *h,
void *data,
int 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); cuhd_handler* handler = static_cast<cuhd_handler*>(h);
uhd::tx_metadata_t md; uhd::tx_metadata_t md;
md.start_of_burst = true; md.start_of_burst = is_start_of_burst;
md.end_of_burst = true; md.end_of_burst = is_end_of_burst;
md.has_time_spec = true; md.has_time_spec = true;
md.time_spec = uhd::time_spec_t(secs, frac_secs); md.time_spec = uhd::time_spec_t(secs, frac_secs);
if (blocking) { return handler->tx_stream->send(data, nsamples, md);
int n=0,p;
complex_t *data_c = (complex_t*) data;
do {
p=handler->tx_stream->send(&data_c[n], nsamples-n, md);
md.has_time_spec = false;
if (p == -1) {
return -1;
}
n+=p;
} while(n<nsamples);
return nsamples;
} else {
return handler->tx_stream->send(data, nsamples, md, 0.0);
}
} }

@ -261,7 +261,7 @@ int main(int argc, char **argv) {
case DECODE_SIB: case DECODE_SIB:
/* We are looking for SI Blocks, search only in appropiate places */ /* We are looking for SI Blocks, search only in appropiate places */
if ((ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { 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), n = ue_dl_decode_sib(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), SIRNTI,
((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);

@ -394,7 +394,7 @@ int main(int argc, char **argv) {
if (prog_args.rnti != SIRNTI) { if (prog_args.rnti != SIRNTI) {
n = ue_dl_decode(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync)); n = ue_dl_decode(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync));
} else { } else {
n = ue_dl_decode_sib(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync), n = ue_dl_decode_sib(&ue_dl, sf_buffer, data_packed, ue_sync_get_sfidx(&ue_sync), SIRNTI,
((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
} }
if (n < 0) { if (n < 0) {

@ -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) { int cuhd_recv_wrapper_timed(void *h, void *data, uint32_t nsamples, timestamp_t *uhd_time) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv_timed(h, data, nsamples, 1, &uhd_time->full_secs, &uhd_time->frac_secs); return cuhd_recv_with_time(h, data, nsamples, &uhd_time->full_secs, &uhd_time->frac_secs);
} }
extern float mean_exec_time; extern float mean_exec_time;
@ -291,7 +291,7 @@ int rar_to_ra_pusch(rar_msg_t *rar, ra_pusch_t *ra, uint32_t nof_prb) {
} }
ra->type2_alloc.riv = riv; ra->type2_alloc.riv = riv;
ra->mcs_idx = rar->mcs; ra->mcs_idx = rar->mcs;
printf("b: %d, RIV: %d\n", b, riv);
ra_type2_from_riv(riv, &ra->type2_alloc.L_crb, &ra->type2_alloc.RB_start, ra_type2_from_riv(riv, &ra->type2_alloc.L_crb, &ra->type2_alloc.RB_start,
nof_prb, nof_prb); nof_prb, nof_prb);
@ -315,6 +315,7 @@ int main(int argc, char **argv) {
timestamp_t uhd_time; timestamp_t uhd_time;
timestamp_t next_tx_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};
uint8_t data[100];
parse_args(&prog_args, argc, argv); parse_args(&prog_args, argc, argv);
@ -383,8 +384,9 @@ int main(int argc, char **argv) {
refsignal_ul_t drms; refsignal_ul_t drms;
refsignal_drms_pusch_cfg_t pusch_cfg; refsignal_drms_pusch_cfg_t pusch_cfg;
pusch_cfg.nof_prb = 3;
bzero(&pusch_cfg, sizeof(refsignal_drms_pusch_cfg_t)); 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)) { if (refsignal_ul_init(&drms, cell)) {
fprintf(stderr, "Error initiating refsignal_ul\n"); fprintf(stderr, "Error initiating refsignal_ul\n");
exit(-1); exit(-1);
@ -395,7 +397,9 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
for (uint32_t i=0;i<2;i++) { for (uint32_t i=0;i<2;i++) {
refsignal_dmrs_pusch_gen(&drms, &pusch_cfg, 2*4+i, &drms_signal[i*RE_X_RB*pusch_cfg.nof_prb]); 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)) { if (pusch_init(&pusch, cell)) {
@ -448,6 +452,7 @@ int main(int argc, char **argv) {
cuhd_start_rx_stream(uhd); cuhd_start_rx_stream(uhd);
struct timeval tdata[3]; struct timeval tdata[3];
uint16_t ra_rnti;
/* Main loop */ /* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) { while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
@ -485,11 +490,10 @@ int main(int argc, char **argv) {
timestamp_add(&next_tx_time, 0, 0.01); // send next frame (10 ms) timestamp_add(&next_tx_time, 0, 0.01); // send next frame (10 ms)
printf("Send prach sfn: %d. Last frame time = %.6f, send prach time = %.6f\n", printf("Send prach sfn: %d. Last frame time = %.6f, send prach time = %.6f\n",
sfn, timestamp_real(&uhd_time), timestamp_real(&next_tx_time)); sfn, timestamp_real(&uhd_time), timestamp_real(&next_tx_time));
cuhd_send_timed(uhd, prach_buffers[7], prach_buffer_len, 1, cuhd_send_timed(uhd, prach_buffers[7], prach_buffer_len,
next_tx_time.full_secs, next_tx_time.frac_secs); next_tx_time.full_secs, next_tx_time.frac_secs);
uint16_t ra_rnti = 2; ra_rnti = 2;
ue_dl_set_rnti(&ue_dl, ra_rnti);
rar_window_start = sfn+1; rar_window_start = sfn+1;
rar_window_stop = sfn+3; rar_window_stop = sfn+3;
state = RECV_RAR; state = RECV_RAR;
@ -499,29 +503,32 @@ int main(int argc, char **argv) {
if ((sfn == rar_window_start && ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) { if ((sfn == rar_window_start && ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) {
gettimeofday(&tdata[1], NULL); gettimeofday(&tdata[1], NULL);
printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, ue_sync_get_sfidx(&ue_sync)); printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, ue_sync_get_sfidx(&ue_sync));
n = ue_dl_decode(&ue_dl, sf_buffer, data_rx, 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));
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) { } else if (n > 0) {
printf("RAR received %d bits: ", n);
vec_fprint_hex(stdout, data_rx, n); gettimeofday(&tdata[2], NULL);
get_time_interval(tdata);
printf("time exec DL: %d\n",tdata[0].tv_usec);
gettimeofday(&tdata[1], NULL);
rar_unpack(data_rx, &rar_msg); rar_unpack(data_rx, &rar_msg);
rar_msg_fprint(stdout, &rar_msg); rar_msg_fprint(stdout, &rar_msg);
pusch_set_rnti(&pusch, rar_msg.temp_c_rnti);
rar_to_ra_pusch(&rar_msg, &ra_pusch, cell.nof_prb); rar_to_ra_pusch(&rar_msg, &ra_pusch, cell.nof_prb);
ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb); ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb);
ra_ul_alloc(&prb_alloc, &ra_pusch, 0, cell.nof_prb); ra_ul_alloc(&prb_alloc, &ra_pusch, 0, cell.nof_prb);
printf("Sending ConnectionRequest in sfn: %d sf_idx: %d\n", sfn, ue_sync_get_sfidx(&ue_sync));
verbose=VERBOSE_INFO;
if (harq_setup_ul(&pusch_harq, ra_pusch.mcs, 0, (ue_sync_get_sfidx(&ue_sync)+6)%10, &prb_alloc)) { if (harq_setup_ul(&pusch_harq, ra_pusch.mcs, 0, (ue_sync_get_sfidx(&ue_sync)+6)%10, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n"); fprintf(stderr, "Error configuring HARQ process\n");
exit(-1);; exit(-1);;
} }
if (pusch_encode(&pusch, &pusch_harq, (uint8_t*) conn_request_msg, sf_symbols)) {
bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs);
if (pusch_encode_rnti(&pusch, &pusch_harq, data, rar_msg.temp_c_rnti, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
exit(-1); exit(-1);
} }
@ -531,16 +538,32 @@ int main(int argc, char **argv) {
lte_ifft_run_sf(&fft, sf_symbols, ul_signal); lte_ifft_run_sf(&fft, sf_symbols, ul_signal);
ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
timestamp_copy(&next_tx_time, &uhd_time);
timestamp_add(&next_tx_time, 0, 0.006); // send after 6 sub-frames (6 ms)
printf("Send PUSCH sfn: %d. Last frame time = %.6f, send PUSCH time = %.6f\n",
sfn, timestamp_real(&uhd_time), timestamp_real(&next_tx_time));
gettimeofday(&tdata[2], NULL); gettimeofday(&tdata[2], NULL);
get_time_interval(tdata); get_time_interval(tdata);
printf("time exec: %d\n",tdata[0].tv_usec); printf("time exec UL: %d\n",tdata[0].tv_usec);
cuhd_send_timed(uhd, ul_signal, SF_LEN_PRB(cell.nof_prb), 1,
next_tx_time.full_secs, next_tx_time.frac_secs); gettimeofday(&tdata[1], NULL);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
gettimeofday(&tdata[2], NULL);
get_time_interval(tdata);
printf("time to stop RX: %d\n",tdata[0].tv_usec);
ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
float time_adv_sec = ((float) rar_msg.timing_adv_cmd - 31 - 25) * 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);
cuhd_send_timed(uhd, ul_signal, SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
go_exit = 1; go_exit = 1;
} }
if (sfn >= rar_window_stop) { if (sfn >= rar_window_stop) {

@ -84,6 +84,12 @@ LIBLTE_API int pdsch_encode(pdsch_t *q,
uint8_t *data, uint8_t *data,
cf_t *sf_symbols[MAX_PORTS]); cf_t *sf_symbols[MAX_PORTS]);
LIBLTE_API int pdsch_encode_rnti(pdsch_t *q,
harq_t *harq_process,
uint8_t *data,
uint16_t rnti,
cf_t *sf_symbols[MAX_PORTS]);
LIBLTE_API int pdsch_decode(pdsch_t *q, LIBLTE_API int pdsch_decode(pdsch_t *q,
harq_t *harq_process, harq_t *harq_process,
cf_t *sf_symbols, cf_t *sf_symbols,
@ -91,6 +97,14 @@ LIBLTE_API int pdsch_decode(pdsch_t *q,
float noise_estimate, float noise_estimate,
uint8_t *data); uint8_t *data);
LIBLTE_API int pdsch_decode_rnti(pdsch_t *q,
harq_t *harq_process,
cf_t *sf_symbols,
cf_t *ce[MAX_PORTS],
float noise_estimate,
uint16_t rnti,
uint8_t *data);
LIBLTE_API float pdsch_average_noi(pdsch_t *q); LIBLTE_API float pdsch_average_noi(pdsch_t *q);
LIBLTE_API uint32_t pdsch_last_noi(pdsch_t *q); LIBLTE_API uint32_t pdsch_last_noi(pdsch_t *q);

@ -92,12 +92,25 @@ LIBLTE_API int pusch_encode(pusch_t *q,
uint8_t *data, uint8_t *data,
cf_t *sf_symbols); cf_t *sf_symbols);
LIBLTE_API int pusch_encode_rnti(pusch_t *q,
harq_t *harq_process,
uint8_t *data,
uint16_t rnti,
cf_t *sf_symbols);
LIBLTE_API int pusch_uci_encode(pusch_t *q, LIBLTE_API int pusch_uci_encode(pusch_t *q,
harq_t *harq_process, harq_t *harq_process,
uint8_t *data, uint8_t *data,
uci_data_t uci_data, uci_data_t uci_data,
cf_t *sf_symbols); cf_t *sf_symbols);
LIBLTE_API int pusch_uci_encode_rnti(pusch_t *q,
harq_t *harq,
uint8_t *data,
uci_data_t uci_data,
uint16_t rnti,
cf_t *sf_symbols);
LIBLTE_API int pusch_decode(pusch_t *q, LIBLTE_API int pusch_decode(pusch_t *q,
harq_t *harq_process, harq_t *harq_process,
cf_t *sf_symbols, cf_t *sf_symbols,

@ -89,10 +89,17 @@ LIBLTE_API int ue_dl_decode(ue_dl_t * q,
uint8_t *data, uint8_t *data,
uint32_t sf_idx); uint32_t sf_idx);
LIBLTE_API int ue_dl_decode_rnti(ue_dl_t * q,
cf_t *input,
uint8_t *data,
uint16_t rnti,
uint32_t sf_idx);
LIBLTE_API int ue_dl_decode_sib(ue_dl_t * q, LIBLTE_API int ue_dl_decode_sib(ue_dl_t * q,
cf_t *input, cf_t *input,
uint8_t * data, uint8_t * data,
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti,
uint32_t rvidx); uint32_t rvidx);
LIBLTE_API void ue_dl_reset(ue_dl_t *q); LIBLTE_API void ue_dl_reset(ue_dl_t *q);

@ -284,13 +284,10 @@ int refsignal_dmrs_pusch_gen(refsignal_ul_t *q, refsignal_drms_pusch_cfg_t *cfg,
u, v, alpha, N_sz, get_q(u,v,N_sz)); u, v, alpha, N_sz, get_q(u,v,N_sz));
} }
vec_fprint_f(stdout, q->tmp_arg, RE_X_RB*cfg->nof_prb);
// Do complex exponential and adjust amplitude // Do complex exponential and adjust amplitude
for (int i=0;i<RE_X_RB*cfg->nof_prb;i++) { for (int i=0;i<RE_X_RB*cfg->nof_prb;i++) {
r_pusch[i] = cfg->beta_pusch * cexpf(I*(q->tmp_arg[i] + alpha*i)); r_pusch[i] = cfg->beta_pusch * cexpf(I*(q->tmp_arg[i] + alpha*i));
} }
vec_fprint_c(stdout, r_pusch, RE_X_RB*cfg->nof_prb);
ret = 0; ret = 0;
} }
return ret; return ret;

@ -302,6 +302,10 @@ void pdsch_free(pdsch_t *q) {
} }
/* 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
*/
int pdsch_set_rnti(pdsch_t *q, uint16_t rnti) { int pdsch_set_rnti(pdsch_t *q, uint16_t rnti) {
uint32_t i; uint32_t i;
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
@ -315,10 +319,27 @@ int pdsch_set_rnti(pdsch_t *q, uint16_t rnti) {
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate, uint8_t *data) {
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
harq != NULL)
{
if (q->rnti_is_set) {
return pdsch_decode_rnti(q, harq, sf_symbols, ce, noise_estimate, q->rnti, data);
} else {
fprintf(stderr, "Must call pdsch_set_rnti() before calling pdsch_decode()\n");
return LIBLTE_ERROR;
}
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}
}
/** Decodes the PDSCH from the received symbols /** Decodes the PDSCH from the received symbols
*/ */
int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate, uint8_t *data) int pdsch_decode_rnti(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS],
float noise_estimate, uint16_t rnti, uint8_t *data)
{ {
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
@ -331,71 +352,90 @@ int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS]
harq != NULL) harq != NULL)
{ {
if (q->rnti_is_set) { INFO("Decoding PDSCH SF: %d, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
INFO("Decoding PDSCH SF: %d, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", /* number of layers equals number of ports */
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pdsch_x[i];
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
/* number of layers equals number of ports */ /* extract symbols */
for (i = 0; i < q->cell.nof_ports; i++) { n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->dl_alloc, harq->sf_idx);
x[i] = q->pdsch_x[i]; if (n != harq->nof_re) {
} fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); return LIBLTE_ERROR;
}
/* extract symbols */ /* extract channel estimates */
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->dl_alloc, harq->sf_idx); for (i = 0; i < q->cell.nof_ports; i++) {
n = pdsch_get(q, ce[i], q->ce[i], &harq->dl_alloc, harq->sf_idx);
if (n != harq->nof_re) { if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
}
/* extract channel estimates */ /* TODO: only diversity is supported */
for (i = 0; i < q->cell.nof_ports; i++) { if (q->cell.nof_ports == 1) {
n = pdsch_get(q, ce[i], q->ce[i], &harq->dl_alloc, harq->sf_idx); /* no need for layer demapping */
if (n != harq->nof_re) { predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d,
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); harq->nof_re, noise_estimate);
return LIBLTE_ERROR; } else {
} predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports,
} harq->nof_re, noise_estimate);
layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports,
harq->nof_re / q->cell.nof_ports);
}
/* TODO: only diversity is supported */ /* demodulate symbols
if (q->cell.nof_ports == 1) { * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
/* no need for layer demapping */ * thus we don't need tot set it in the LLRs normalization
predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d, */
harq->nof_re, noise_estimate); demod_soft_sigma_set(&q->demod, sqrt(0.5));
} else { demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]);
predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports, demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, harq->nof_re);
harq->nof_re, noise_estimate);
layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports, /* descramble */
harq->nof_re / q->cell.nof_ports); if (rnti != q->rnti) {
sequence_t seq;
if (sequence_pdsch(&seq, rnti, 0, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
return LIBLTE_ERROR;
} }
scrambling_f_offset(&seq, q->pdsch_e, 0, harq->nof_bits);
sequence_free(&seq);
} else {
scrambling_f_offset(&q->seq_pdsch[harq->sf_idx], q->pdsch_e, 0, harq->nof_bits);
}
/* demodulate symbols return dlsch_decode(&q->dl_sch, harq, q->pdsch_e, data);
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
demod_soft_sigma_set(&q->demod, sqrt(0.5));
demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, harq->nof_re);
/* descramble */ } else {
scrambling_f_offset(&q->seq_pdsch[harq->sf_idx], q->pdsch_e, 0, harq->nof_bits); return LIBLTE_ERROR_INVALID_INPUTS;
}
}
return dlsch_decode(&q->dl_sch, harq, q->pdsch_e, data); int pdsch_encode(pdsch_t *q, harq_t *harq, uint8_t *data, cf_t *sf_symbols[MAX_PORTS])
{
if (q != NULL &&
data != NULL &&
harq != NULL)
{
if (q->rnti_is_set) {
return pdsch_encode_rnti(q, harq, data, q->rnti, sf_symbols);
} else { } else {
fprintf(stderr, "Must call pdsch_set_rnti() before calling pdsch_decode()\n"); fprintf(stderr, "Must call pdsch_set_rnti() to set the encoder/decoder RNTI\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} else { } else {
return LIBLTE_ERROR_INVALID_INPUTS; return LIBLTE_ERROR_INVALID_INPUTS;
} }
} }
/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission /** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission
*/ */
int pdsch_encode(pdsch_t *q, harq_t *harq, uint8_t *data, cf_t *sf_symbols[MAX_PORTS]) int pdsch_encode_rnti(pdsch_t *q, harq_t *harq, uint8_t *data, uint16_t rnti, cf_t *sf_symbols[MAX_PORTS])
{ {
int i; int i;
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
@ -407,64 +447,69 @@ int pdsch_encode(pdsch_t *q, harq_t *harq, uint8_t *data, cf_t *sf_symbols[MAX_P
harq != NULL) harq != NULL)
{ {
if (q->rnti_is_set) { for (i=0;i<q->cell.nof_ports;i++) {
for (i=0;i<q->cell.nof_ports;i++) { if (sf_symbols[i] == NULL) {
if (sf_symbols[i] == NULL) {
return LIBLTE_ERROR_INVALID_INPUTS;
}
}
if (harq->mcs.tbs == 0) {
return LIBLTE_ERROR_INVALID_INPUTS; return LIBLTE_ERROR_INVALID_INPUTS;
} }
}
if (harq->mcs.tbs > harq->nof_bits) { if (harq->mcs.tbs == 0) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits); return LIBLTE_ERROR_INVALID_INPUTS;
return LIBLTE_ERROR_INVALID_INPUTS; }
}
if (harq->nof_re > q->max_re) { if (harq->mcs.tbs > harq->nof_bits) {
fprintf(stderr, fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", return LIBLTE_ERROR_INVALID_INPUTS;
harq->nof_re, q->max_re, q->cell.nof_prb); }
return LIBLTE_ERROR_INVALID_INPUTS;
}
INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", if (harq->nof_re > q->max_re) {
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
harq->nof_re, q->max_re, q->cell.nof_prb);
return LIBLTE_ERROR_INVALID_INPUTS;
}
/* number of layers equals number of ports */ INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
for (i = 0; i < q->cell.nof_ports; i++) { harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
x[i] = q->pdsch_x[i];
} /* number of layers equals number of ports */
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pdsch_x[i];
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
if (dlsch_encode(&q->dl_sch, harq, data, q->pdsch_e)) { if (dlsch_encode(&q->dl_sch, harq, data, q->pdsch_e)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
return LIBLTE_ERROR;
}
if (rnti != q->rnti) {
sequence_t seq;
if (sequence_pdsch(&seq, rnti, 0, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
scrambling_b_offset(&seq, (uint8_t*) q->pdsch_e, 0, harq->nof_bits);
sequence_free(&seq);
} else {
scrambling_b_offset(&q->seq_pdsch[harq->sf_idx], (uint8_t*) q->pdsch_e, 0, harq->nof_bits); scrambling_b_offset(&q->seq_pdsch[harq->sf_idx], (uint8_t*) q->pdsch_e, 0, harq->nof_bits);
}
mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pdsch_e, q->pdsch_d, harq->nof_bits); mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pdsch_e, q->pdsch_d, harq->nof_bits);
/* TODO: only diversity supported */ /* TODO: only diversity supported */
if (q->cell.nof_ports > 1) { if (q->cell.nof_ports > 1) {
layermap_diversity(q->pdsch_d, x, q->cell.nof_ports, harq->nof_re); layermap_diversity(q->pdsch_d, x, q->cell.nof_ports, harq->nof_re);
precoding_diversity(&q->precoding, x, q->pdsch_symbols, q->cell.nof_ports, precoding_diversity(&q->precoding, x, q->pdsch_symbols, q->cell.nof_ports,
harq->nof_re / q->cell.nof_ports); harq->nof_re / q->cell.nof_ports);
} else {
memcpy(q->pdsch_symbols[0], q->pdsch_d, harq->nof_re * sizeof(cf_t));
}
/* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) {
pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], &harq->dl_alloc, harq->sf_idx);
}
ret = LIBLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Must call pdsch_set_rnti() to set the encoder/decoder RNTI\n"); memcpy(q->pdsch_symbols[0], q->pdsch_d, harq->nof_re * sizeof(cf_t));
} }
/* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) {
pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], &harq->dl_alloc, harq->sf_idx);
}
ret = LIBLTE_SUCCESS;
} }
return ret; return ret;
} }

@ -278,6 +278,9 @@ void pusch_free(pusch_t *q) {
} }
/* 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 */
int pusch_set_rnti(pusch_t *q, uint16_t rnti) { int pusch_set_rnti(pusch_t *q, uint16_t rnti) {
uint32_t i; uint32_t i;
@ -292,7 +295,6 @@ int pusch_set_rnti(pusch_t *q, uint16_t rnti) {
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
/** Decodes the PUSCH from the received symbols /** Decodes the PUSCH from the received symbols
*/ */
int pusch_decode(pusch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data) int pusch_decode(pusch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data)
@ -351,16 +353,38 @@ int pusch_decode(pusch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noi
} }
} }
int pusch_encode(pusch_t *q, harq_t *harq_process, uint8_t *data, cf_t *sf_symbols) int pusch_encode_rnti(pusch_t *q, harq_t *harq_process, uint8_t *data, uint16_t rnti, cf_t *sf_symbols)
{ {
uci_data_t uci_data; uci_data_t uci_data;
bzero(&uci_data, sizeof(uci_data_t)); bzero(&uci_data, sizeof(uci_data_t));
return pusch_uci_encode(q, harq_process, data, uci_data, sf_symbols); return pusch_uci_encode_rnti(q, harq_process, data, uci_data, rnti, sf_symbols);
}
int pusch_encode(pusch_t *q, harq_t *harq_process, uint8_t *data, cf_t *sf_symbols)
{
if (q->rnti_is_set) {
uci_data_t uci_data;
bzero(&uci_data, sizeof(uci_data_t));
return pusch_uci_encode_rnti(q, harq_process, data, uci_data, q->rnti, sf_symbols);
} else {
fprintf(stderr, "Must call pusch_set_rnti() to set the encoder/decoder RNTI\n");
return LIBLTE_ERROR;
}
}
int pusch_uci_encode(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_data, cf_t *sf_symbols)
{
if (q->rnti_is_set) {
return pusch_uci_encode_rnti(q, harq, data, uci_data, q->rnti, sf_symbols);
} else {
fprintf(stderr, "Must call pusch_set_rnti() to set the encoder/decoder RNTI\n");
return LIBLTE_ERROR;
}
} }
/** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission /** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission
*/ */
int pusch_uci_encode(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_data, cf_t *sf_symbols) int pusch_uci_encode_rnti(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_data, uint16_t rnti, cf_t *sf_symbols)
{ {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
@ -368,41 +392,52 @@ int pusch_uci_encode(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_dat
data != NULL && data != NULL &&
harq != NULL) harq != NULL)
{ {
if (q->rnti_is_set) { if (harq->mcs.tbs > harq->nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
return LIBLTE_ERROR_INVALID_INPUTS;
}
if (harq->mcs.tbs > harq->nof_bits) { if (harq->nof_re > q->max_re) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits); fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n",
return LIBLTE_ERROR_INVALID_INPUTS; harq->nof_re, q->max_re, q->cell.nof_prb);
} return LIBLTE_ERROR_INVALID_INPUTS;
}
if (harq->nof_re > q->max_re) { INFO("Encoding PUSCH SF: %d, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n", harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
harq->nof_re, q->max_re, q->cell.nof_prb);
return LIBLTE_ERROR_INVALID_INPUTS;
}
INFO("Encoding PUSCH SF: %d, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", bzero(q->pusch_q, harq->nof_bits);
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); if (ulsch_uci_encode(&q->dl_sch, harq, data, uci_data, q->pusch_g, q->pusch_q)) {
fprintf(stderr, "Error encoding TB\n");
return LIBLTE_ERROR;
}
printf("before scram: ");
vec_fprint_b(stdout, q->pusch_q, harq->nof_bits);
if (ulsch_uci_encode(&q->dl_sch, harq, data, uci_data, q->pusch_g, q->pusch_q)) { if (rnti != q->rnti) {
fprintf(stderr, "Error encoding TB\n"); sequence_t seq;
if (sequence_pusch(&seq, rnti, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
scrambling_b_offset_pusch(&seq, (uint8_t*) q->pusch_q, 0, harq->nof_bits);
sequence_free(&seq);
} else {
scrambling_b_offset_pusch(&q->seq_pusch[harq->sf_idx], (uint8_t*) q->pusch_q, 0, harq->nof_bits); scrambling_b_offset_pusch(&q->seq_pusch[harq->sf_idx], (uint8_t*) q->pusch_q, 0, harq->nof_bits);
}
mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, harq->nof_bits); printf("after scram: ");
vec_fprint_b(stdout, q->pusch_q, harq->nof_bits);
dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z, mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, harq->nof_bits);
harq->ul_alloc.L_prb, harq->nof_symb);
/* mapping to resource elements */ dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z,
pusch_put(q, harq, q->pusch_z, sf_symbols); harq->ul_alloc.L_prb, harq->nof_symb);
ret = LIBLTE_SUCCESS; /* mapping to resource elements */
} else { pusch_put(q, harq, q->pusch_z, sf_symbols);
fprintf(stderr, "Must call pusch_set_rnti() to set the encoder/decoder RNTI\n");
} ret = LIBLTE_SUCCESS;
} }
return ret; return ret;
} }

@ -194,7 +194,6 @@ int main(int argc, char **argv) {
frame_cnt = 0; frame_cnt = 0;
last_peak = 0; last_peak = 0;
mean_peak = 0; mean_peak = 0;
int peak_offset = 0;
float cfo; float cfo;
float mean_cfo = 0; float mean_cfo = 0;
uint32_t m0, m1; uint32_t m0, m1;
@ -205,12 +204,27 @@ int main(int argc, char **argv) {
bzero(&ssync, sizeof(sync_t)); bzero(&ssync, sizeof(sync_t));
ssync.fft_size = fft_size; 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) { while(frame_cnt < nof_frames || nof_frames == -1) {
n = cuhd_recv(uhd, buffer, flen - peak_offset, 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);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error receiving samples\n"); fprintf(stderr, "Error receiving samples\n");
exit(-1); exit(-1);
} }
is_first = false;
peak_idx = pss_synch_find_pss(&pss, buffer, &peak_value); peak_idx = pss_synch_find_pss(&pss, buffer, &peak_value);
if (peak_idx < 0) { if (peak_idx < 0) {
@ -223,6 +237,12 @@ int main(int argc, char **argv) {
if (peak_value >= threshold) { if (peak_value >= threshold) {
nof_det++; 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) { if (peak_idx >= fft_size) {
// Estimate CFO // Estimate CFO
@ -288,10 +308,10 @@ int main(int argc, char **argv) {
frame_cnt++; frame_cnt++;
printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " printf("[%5d]: Pos: %5d (%f), 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", "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f\%\r",
frame_cnt, frame_cnt,
peak_idx, peak_idx, period_diff*1000000,
peak_value, mean_peak, peak_value, mean_peak,
(float) nof_det/frame_cnt, (float) nof_det/frame_cnt,
(float) nof_nopeakdet/frame_cnt, mean_cfo*15, (float) nof_nopeakdet/frame_cnt, mean_cfo*15,

@ -142,6 +142,10 @@ void ue_dl_free(ue_dl_t *q) {
} }
} }
/* 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_dl_set_rnti(ue_dl_t *q, uint16_t rnti) { void ue_dl_set_rnti(ue_dl_t *q, uint16_t rnti) {
q->current_rnti = rnti; q->current_rnti = rnti;
pdsch_set_rnti(&q->pdsch, rnti); pdsch_set_rnti(&q->pdsch, rnti);
@ -167,10 +171,14 @@ const uint32_t nof_common_formats = 2;
* - PDSCH decoding: Decode TB scrambling with RNTI given by ue_dl_set_rnti() * - 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) { 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, 0); return ue_dl_decode_sib(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_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32_t rvidx) 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; uint32_t cfi, i;
float cfi_corr; float cfi_corr;
@ -207,12 +215,12 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui
} }
/* Generate PDCCH candidates */ /* Generate PDCCH candidates */
if (q->current_rnti == SIRNTI) { if (rnti == SIRNTI) {
nof_locations = pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, cfi); nof_locations = pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, cfi);
formats = common_formats; formats = common_formats;
nof_formats = nof_common_formats; nof_formats = nof_common_formats;
} else { } else {
nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, q->current_rnti); nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
formats = ue_formats; formats = ue_formats;
nof_formats = nof_ue_formats; nof_formats = nof_ue_formats;
} }
@ -233,16 +241,16 @@ 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); INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
if (crc_rem == q->current_rnti) { if (crc_rem == rnti) {
found_dci++; found_dci++;
q->nof_pdcch_detected++; q->nof_pdcch_detected++;
if (dci_msg_to_ra_dl(&dci_msg, q->current_rnti, q->cell, cfi, &ra_dl)) { if (dci_msg_to_ra_dl(&dci_msg, rnti, q->cell, cfi, &ra_dl)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
if (q->current_rnti != SIRNTI) { if (rnti != SIRNTI) {
rvidx = ra_dl.rv_idx; rvidx = ra_dl.rv_idx;
} }
if (harq_setup_dl(&q->harq_process[0], ra_dl.mcs, rvidx, sf_idx, &ra_dl.prb_alloc)) { if (harq_setup_dl(&q->harq_process[0], ra_dl.mcs, rvidx, sf_idx, &ra_dl.prb_alloc)) {
@ -250,9 +258,9 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) { if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) {
ret = pdsch_decode(&q->pdsch, &q->harq_process[0], q->sf_symbols, ret = pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols,
q->ce, chest_dl_get_noise_estimate(&q->chest), q->ce, chest_dl_get_noise_estimate(&q->chest),
data); rnti, data);
if (ret == LIBLTE_ERROR) { if (ret == LIBLTE_ERROR) {
q->pkt_errors++; q->pkt_errors++;
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) { } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {

@ -35,6 +35,7 @@ for prb=3
if (error(k) > 10^-3) if (error(k) > 10^-3)
k=1; k=1;
end end
read_real
k=k+1; k=k+1;
end end
end end

Loading…
Cancel
Save