mirror of https://github.com/PentHertz/srsLTE.git
Fixed PRACH example
This commit is contained in:
parent
d5a0be5e92
commit
99df252279
|
@ -65,17 +65,9 @@ LIBLTE_API double cuhd_set_rx_freq_offset(void *h,
|
|||
double freq,
|
||||
double off);
|
||||
|
||||
LIBLTE_API int cuhd_recv(void *h,
|
||||
void *data,
|
||||
uint32_t nsamples,
|
||||
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 void cuhd_get_time(void *h,
|
||||
time_t *secs,
|
||||
double *frac_secs);
|
||||
|
||||
LIBLTE_API double cuhd_set_tx_srate(void *h,
|
||||
double freq);
|
||||
|
@ -93,6 +85,32 @@ LIBLTE_API double cuhd_set_tx_freq_offset(void *h,
|
|||
double freq,
|
||||
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,
|
||||
void *data,
|
||||
uint32_t nsamples,
|
||||
|
@ -102,10 +120,18 @@ LIBLTE_API int cuhd_send(void *h,
|
|||
LIBLTE_API int cuhd_send_timed(void *h,
|
||||
void *data,
|
||||
int nsamples,
|
||||
int blocking,
|
||||
time_t 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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -156,11 +156,12 @@ double cuhd_set_rx_srate(void *h, double freq)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -213,39 +214,56 @@ int cuhd_recv(void *h, void *data, uint32_t nsamples, bool blocking)
|
|||
}
|
||||
}
|
||||
|
||||
int cuhd_recv_timed(void *h,
|
||||
void *data,
|
||||
uint32_t nsamples,
|
||||
bool blocking,
|
||||
time_t *secs,
|
||||
double *frac_secs)
|
||||
int cuhd_recv_with_time(void *h,
|
||||
void *data,
|
||||
uint32_t nsamples,
|
||||
time_t *secs,
|
||||
double *frac_secs)
|
||||
{
|
||||
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
|
||||
uhd::rx_metadata_t md;
|
||||
*secs = -1;
|
||||
*frac_secs = -1;
|
||||
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);
|
||||
int p = 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;
|
||||
*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)
|
||||
|
@ -301,32 +319,28 @@ int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int cuhd_send_timed(void *h,
|
||||
void *data,
|
||||
int nsamples,
|
||||
int blocking,
|
||||
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);
|
||||
uhd::tx_metadata_t md;
|
||||
md.start_of_burst = true;
|
||||
md.end_of_burst = true;
|
||||
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);
|
||||
if (blocking) {
|
||||
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);
|
||||
}
|
||||
return handler->tx_stream->send(data, nsamples, md);
|
||||
}
|
||||
|
|
|
@ -261,7 +261,7 @@ 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),
|
||||
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);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
||||
|
|
|
@ -394,7 +394,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),
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
|
@ -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->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,
|
||||
nof_prb, nof_prb);
|
||||
|
||||
|
@ -315,7 +315,8 @@ int main(int argc, char **argv) {
|
|||
timestamp_t uhd_time;
|
||||
timestamp_t next_tx_time;
|
||||
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);
|
||||
|
||||
printf("Opening UHD device...\n");
|
||||
|
@ -383,8 +384,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
refsignal_ul_t drms;
|
||||
refsignal_drms_pusch_cfg_t pusch_cfg;
|
||||
pusch_cfg.nof_prb = 3;
|
||||
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);
|
||||
|
@ -395,7 +397,9 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
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)) {
|
||||
|
@ -420,7 +424,7 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
bzero(ul_signal, sizeof(cf_t) * SF_LEN_PRB(cell.nof_prb));
|
||||
|
||||
|
||||
cf_t *sf_symbols = vec_malloc(sizeof(cf_t) * SF_LEN_PRB(cell.nof_prb));
|
||||
if (!sf_symbols) {
|
||||
perror("malloc");
|
||||
|
@ -444,10 +448,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
// Register Ctrl+C handler
|
||||
signal(SIGINT, sig_int_handler);
|
||||
|
||||
|
||||
cuhd_start_rx_stream(uhd);
|
||||
|
||||
struct timeval tdata[3];
|
||||
uint16_t ra_rnti;
|
||||
|
||||
/* Main loop */
|
||||
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)
|
||||
printf("Send prach sfn: %d. Last frame time = %.6f, send prach time = %.6f\n",
|
||||
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);
|
||||
|
||||
uint16_t ra_rnti = 2;
|
||||
ue_dl_set_rnti(&ue_dl, ra_rnti);
|
||||
ra_rnti = 2;
|
||||
rar_window_start = sfn+1;
|
||||
rar_window_stop = sfn+3;
|
||||
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) {
|
||||
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(&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) {
|
||||
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
||||
} 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_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);
|
||||
ra_pusch_fprint(stdout, &ra_pusch, 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)) {
|
||||
fprintf(stderr, "Error configuring HARQ process\n");
|
||||
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");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -531,16 +538,32 @@ int main(int argc, char **argv) {
|
|||
|
||||
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);
|
||||
get_time_interval(tdata);
|
||||
printf("time exec: %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);
|
||||
printf("time exec UL: %d\n",tdata[0].tv_usec);
|
||||
|
||||
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;
|
||||
}
|
||||
if (sfn >= rar_window_stop) {
|
||||
|
|
|
@ -84,6 +84,12 @@ LIBLTE_API int pdsch_encode(pdsch_t *q,
|
|||
uint8_t *data,
|
||||
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,
|
||||
harq_t *harq_process,
|
||||
cf_t *sf_symbols,
|
||||
|
@ -91,6 +97,14 @@ LIBLTE_API int pdsch_decode(pdsch_t *q,
|
|||
float noise_estimate,
|
||||
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 uint32_t pdsch_last_noi(pdsch_t *q);
|
||||
|
|
|
@ -92,12 +92,25 @@ LIBLTE_API int pusch_encode(pusch_t *q,
|
|||
uint8_t *data,
|
||||
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,
|
||||
harq_t *harq_process,
|
||||
uint8_t *data,
|
||||
uci_data_t uci_data,
|
||||
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,
|
||||
harq_t *harq_process,
|
||||
cf_t *sf_symbols,
|
||||
|
|
|
@ -89,10 +89,17 @@ LIBLTE_API int ue_dl_decode(ue_dl_t * q,
|
|||
uint8_t *data,
|
||||
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,
|
||||
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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
vec_fprint_f(stdout, q->tmp_arg, RE_X_RB*cfg->nof_prb);
|
||||
|
||||
// Do complex exponential and adjust amplitude
|
||||
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));
|
||||
}
|
||||
vec_fprint_c(stdout, r_pusch, RE_X_RB*cfg->nof_prb);
|
||||
ret = 0;
|
||||
}
|
||||
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) {
|
||||
uint32_t 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;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
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 */
|
||||
|
@ -331,71 +352,90 @@ int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS]
|
|||
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",
|
||||
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
|
||||
|
||||
/* number of layers equals number of 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));
|
||||
|
||||
/* extract symbols */
|
||||
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->dl_alloc, harq->sf_idx);
|
||||
/* number of layers equals number of 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));
|
||||
|
||||
/* extract symbols */
|
||||
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->dl_alloc, harq->sf_idx);
|
||||
if (n != harq->nof_re) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
/* extract channel estimates */
|
||||
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) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
/* extract channel estimates */
|
||||
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) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: only diversity is supported */
|
||||
if (q->cell.nof_ports == 1) {
|
||||
/* no need for layer demapping */
|
||||
predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d,
|
||||
harq->nof_re, noise_estimate);
|
||||
} 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);
|
||||
}
|
||||
|
||||
/* demodulate symbols
|
||||
* 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 */
|
||||
scrambling_f_offset(&q->seq_pdsch[harq->sf_idx], q->pdsch_e, 0, harq->nof_bits);
|
||||
|
||||
return dlsch_decode(&q->dl_sch, harq, q->pdsch_e, data);
|
||||
} else {
|
||||
fprintf(stderr, "Must call pdsch_set_rnti() before calling pdsch_decode()\n");
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: only diversity is supported */
|
||||
if (q->cell.nof_ports == 1) {
|
||||
/* no need for layer demapping */
|
||||
predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d,
|
||||
harq->nof_re, noise_estimate);
|
||||
} 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);
|
||||
}
|
||||
|
||||
/* demodulate symbols
|
||||
* 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 */
|
||||
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);
|
||||
}
|
||||
|
||||
return dlsch_decode(&q->dl_sch, harq, q->pdsch_e, data);
|
||||
|
||||
} else {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
fprintf(stderr, "Must call pdsch_set_rnti() to set the encoder/decoder RNTI\n");
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
} else {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
/** 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;
|
||||
/* 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)
|
||||
{
|
||||
|
||||
if (q->rnti_is_set) {
|
||||
for (i=0;i<q->cell.nof_ports;i++) {
|
||||
if (sf_symbols[i] == NULL) {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (harq->mcs.tbs == 0) {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (harq->mcs.tbs > harq->nof_bits) {
|
||||
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
|
||||
for (i=0;i<q->cell.nof_ports;i++) {
|
||||
if (sf_symbols[i] == NULL) {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (harq->nof_re > q->max_re) {
|
||||
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;
|
||||
}
|
||||
|
||||
INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %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);
|
||||
|
||||
/* number of layers equals number of 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)) {
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* TODO: only diversity supported */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
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,
|
||||
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 {
|
||||
fprintf(stderr, "Must call pdsch_set_rnti() to set the encoder/decoder RNTI\n");
|
||||
}
|
||||
|
||||
if (harq->mcs.tbs == 0) {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
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->nof_re > q->max_re) {
|
||||
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;
|
||||
}
|
||||
|
||||
INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %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);
|
||||
|
||||
/* number of layers equals number of 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)) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pdsch_e, q->pdsch_d, harq->nof_bits);
|
||||
|
||||
/* TODO: only diversity supported */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
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,
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
uint32_t i;
|
||||
|
||||
|
@ -292,7 +295,6 @@ int pusch_set_rnti(pusch_t *q, uint16_t rnti) {
|
|||
return LIBLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/** 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)
|
||||
|
@ -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;
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -368,41 +392,52 @@ int pusch_uci_encode(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_dat
|
|||
data != 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->nof_re > q->max_re) {
|
||||
fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n",
|
||||
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",
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z,
|
||||
harq->ul_alloc.L_prb, harq->nof_symb);
|
||||
|
||||
/* mapping to resource elements */
|
||||
pusch_put(q, harq, q->pusch_z, sf_symbols);
|
||||
|
||||
ret = LIBLTE_SUCCESS;
|
||||
} else {
|
||||
fprintf(stderr, "Must call pusch_set_rnti() to set the encoder/decoder RNTI\n");
|
||||
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->nof_re > q->max_re) {
|
||||
fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n",
|
||||
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",
|
||||
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
|
||||
|
||||
bzero(q->pusch_q, harq->nof_bits);
|
||||
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 (rnti != q->rnti) {
|
||||
sequence_t seq;
|
||||
if (sequence_pusch(&seq, rnti, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
harq->ul_alloc.L_prb, harq->nof_symb);
|
||||
|
||||
/* mapping to resource elements */
|
||||
pusch_put(q, harq, q->pusch_z, sf_symbols);
|
||||
|
||||
ret = LIBLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,6 @@ 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;
|
||||
|
@ -205,12 +204,27 @@ 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) {
|
||||
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) {
|
||||
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) {
|
||||
|
@ -222,7 +236,13 @@ 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
|
||||
|
@ -288,10 +308,10 @@ int main(int argc, char **argv) {
|
|||
|
||||
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",
|
||||
frame_cnt,
|
||||
peak_idx,
|
||||
peak_idx, period_diff*1000000,
|
||||
peak_value, mean_peak,
|
||||
(float) nof_det/frame_cnt,
|
||||
(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) {
|
||||
q->current_rnti = 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()
|
||||
*/
|
||||
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_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32_t rvidx)
|
||||
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, uint16_t rnti, uint32_t rvidx)
|
||||
{
|
||||
uint32_t cfi, i;
|
||||
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 */
|
||||
if (q->current_rnti == SIRNTI) {
|
||||
if (rnti == SIRNTI) {
|
||||
nof_locations = pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, cfi);
|
||||
formats = common_formats;
|
||||
nof_formats = nof_common_formats;
|
||||
} 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;
|
||||
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);
|
||||
|
||||
if (crc_rem == q->current_rnti) {
|
||||
if (crc_rem == rnti) {
|
||||
|
||||
found_dci++;
|
||||
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");
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
if (q->current_rnti != SIRNTI) {
|
||||
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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
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,
|
||||
q->ce, chest_dl_get_noise_estimate(&q->chest),
|
||||
data);
|
||||
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) {
|
||||
|
|
|
@ -35,6 +35,7 @@ for prb=3
|
|||
if (error(k) > 10^-3)
|
||||
k=1;
|
||||
end
|
||||
read_real
|
||||
k=k+1;
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue