PHICH working. PRACH example using UE ITF working

master
ismagom 10 years ago
parent c9b3ce0d06
commit 6eb3f1f484

@ -94,6 +94,10 @@ SRSLTE_API double cuhd_set_tx_freq_offset(void *h,
double freq,
double offset);
SRSLTE_API void cuhd_get_time(void *h,
time_t *secs,
double *frac_secs);
SRSLTE_API int cuhd_send(void *h,
void *data,
uint32_t nsamples,

@ -43,6 +43,7 @@ namespace srslte {
bool init();
bool init(char *args);
void get_time(srslte_timestamp_t *now);
bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time);
bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time);

@ -121,7 +121,7 @@ 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=512");
handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000");
// handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=50000000" + ", num_recv_frames=512");
handler->usrp->set_clock_source("internal");
@ -273,6 +273,16 @@ double cuhd_set_tx_freq_offset(void *h, double freq, double off) {
return handler->usrp->get_tx_freq();
}
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();
if (secs) {
*secs = now.get_full_secs();
}
if (frac_secs) {
*frac_secs = now.get_frac_secs();
}
}
int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking)
{
@ -305,12 +315,12 @@ int cuhd_send_timed(void *h,
}
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)
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;

@ -62,6 +62,10 @@ bool radio_uhd::rx_now(void* buffer, uint32_t nof_samples, srslte_timestamp_t* r
}
}
void radio_uhd::get_time(srslte_timestamp_t *now) {
cuhd_get_time(uhd, &now->full_secs, &now->frac_secs);
}
bool radio_uhd::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time)
{
if (cuhd_send_timed(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs) > 0) {

@ -285,9 +285,6 @@ int rar_unpack(uint8_t *buffer, rar_msg_t *msg)
return(ret);
}
#define kk
#define use_usrp
int main(int argc, char **argv) {
int ret;
srslte_cell_t cell;
@ -308,7 +305,6 @@ int main(int argc, char **argv) {
parse_args(&prog_args, argc, argv);
#ifdef use_usrp
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
@ -329,9 +325,7 @@ int main(int argc, char **argv) {
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);
#endif
#ifdef kk
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
@ -340,16 +334,6 @@ int main(int argc, char **argv) {
printf("Cell not found\n");
exit(0);
}
#else
cell.id = 1;
cell.nof_ports = 1;
cell.nof_prb = 25;
cell.cp = SRSLTE_CP_NORM;
cell.phich_length = SRSLTE_PHICH_NORM;
cell.phich_resources = SRSLTE_PHICH_R_1;
#endif
#ifdef use_usrp
/* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb);
@ -365,7 +349,6 @@ int main(int argc, char **argv) {
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
#endif
if (srslte_ue_mib_init(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
@ -392,6 +375,8 @@ int main(int argc, char **argv) {
exit(-1);
}
srslte_ue_ul_set_cfo_enable(&ue_ul, true);
srslte_pusch_hopping_cfg_t hop_cfg;
bzero(&hop_cfg, sizeof(srslte_pusch_hopping_cfg_t));
srslte_refsignal_drms_pusch_cfg_t drms_cfg;
@ -421,39 +406,28 @@ int main(int argc, char **argv) {
sf_cnt = 0;
#ifdef use_usrp
if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper_timed, uhd)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
cuhd_start_rx_stream(uhd);
#endif
uint16_t ra_rnti;
uint32_t conn_setup_trial = 0;
uint32_t ul_sf_idx = 0;
#ifdef kk
// Register Ctrl+C handler
signal(SIGINT, sig_int_handler);
state = DECODE_MIB;
#else
state = RECV_RAR;
#endif
/* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
#ifdef kk
ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
}
#else
ret = 1;
srslte_timestamp_t rx_time, tx_time;
cf_t dummy[4];
#endif
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
@ -485,7 +459,6 @@ int main(int argc, char **argv) {
break;
case SEND_PRACH:
#ifdef kk
if (((sfn%2) == 1) && (srslte_ue_sync_get_sfidx(&ue_sync) == 1)) {
srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
@ -497,27 +470,15 @@ int main(int argc, char **argv) {
cuhd_send_timed(uhd, prach_buffer, prach_buffer_len,
next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue", prach_buffer, prach_buffer_len*sizeof(cf_t));
ra_rnti = 2;
rar_window_start = sfn+1;
rar_window_stop = sfn+3;
state = RECV_RAR;
}
#else
cuhd_recv_with_time(uhd, dummy, 4, 1, &rx_time.full_secs, &rx_time.frac_secs);
srslte_timestamp_copy(&tx_time, &rx_time);
printf("Transmitting PRACH...\n");
srslte_vec_save_file("srslte_prach_tx", prach_buffers[7], prach_buffer_len*sizeof(cf_t));
while(1) {
srslte_timestamp_add(&tx_time, 0, 0.001); // send every (10 ms)
cuhd_send_timed(uhd, prach_buffers[7], prach_buffer_len,
tx_time.full_secs, tx_time.frac_secs);
}
#endif
break;
case RECV_RAR:
#ifdef kk
if ((sfn == rar_window_start && srslte_ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) {
printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, srslte_ue_sync_get_sfidx(&ue_sync));
@ -527,58 +488,55 @@ int main(int argc, char **argv) {
} else if (n > 0) {
rar_unpack(data_rx, &rar_msg);
//if (rar_msg.RAPID != prog_args.preamble_idx) {
// printf("Found RAR for sequence %d\n", rar_msg.RAPID);
//} else {
//cuhd_stop_rx_stream(uhd);
//cuhd_flush_buffer(uhd);
rar_msg_fprint(stdout, &rar_msg);
srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch);
srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb);
rar_msg_fprint(stdout, &rar_msg);
srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch);
srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb);
srslte_ra_ul_alloc(&ra_pusch.prb_alloc, &ra_pusch, 0, cell.nof_prb);
srslte_ra_ul_alloc(&ra_pusch.prb_alloc, &ra_pusch, 0, cell.nof_prb);
srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs);
srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs);
uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd);
printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta);
float time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS;
if (prog_args.ta_usec >= 0) {
time_adv_sec = prog_args.ta_usec*1e-6;
uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd);
printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta);
float time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS;
if (prog_args.ta_usec >= 0) {
time_adv_sec = prog_args.ta_usec*1e-6;
}
#define N_TX 1
const uint32_t rv[N_TX]={0};
for (int i=0; i<N_TX;i++) {
ra_pusch.rv_idx = rv[i];
ul_sf_idx = (srslte_ue_sync_get_sfidx(&ue_sync)+6+i*8)%10;
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
printf("Setting CFO: %f (%f)\n", cfo, cfo*15000);
srslte_ue_ul_set_cfo(&ue_ul, cfo);
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_pusch, data, ul_sf_idx, rar_msg.temp_c_rnti, ul_signal);
if (n < 0) {
fprintf(stderr, "Error encoding PUSCH\n");
exit(-1);
}
#define N_TX 1
const uint32_t rv[N_TX]={0};
for (int i=0; i<N_TX;i++) {
ra_pusch.rv_idx = rv[i];
ul_sf_idx = (srslte_ue_sync_get_sfidx(&ue_sync)+6+i*8)%10;
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_pusch, data, ul_sf_idx, rar_msg.temp_c_rnti, ul_signal);
if (n < 0) {
fprintf(stderr, "Error encoding PUSCH\n");
exit(-1);
}
srslte_vec_sc_prod_cfc(ul_signal, prog_args.beta_pusch, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_timestamp_copy(&next_tx_time, &uhd_time);
srslte_timestamp_add(&next_tx_time, 0, 0.006 + i*0.008 - time_adv_sec); // send after 6 sub-frames (6 ms)
printf("Send %d samples PUSCH sfn: %d. RV_idx=%d, Last frame time = %.6f "
"send PUSCH time = %.6f TA: %.1f us\n",
SRSLTE_SF_LEN_PRB(cell.nof_prb), sfn, ra_pusch.rv_idx,
srslte_timestamp_real(&uhd_time),
srslte_timestamp_real(&next_tx_time), time_adv_sec*1000000);
cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
//cuhd_start_rx_stream(uhd);
state = RECV_CONNSETUP;
conn_setup_trial = 0;
// }
srslte_vec_sc_prod_cfc(ul_signal, prog_args.beta_pusch, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_timestamp_copy(&next_tx_time, &uhd_time);
srslte_timestamp_add(&next_tx_time, 0, 0.006 + i*0.008 - time_adv_sec); // send after 6 sub-frames (6 ms)
printf("Send %d samples PUSCH sfn: %d. RV_idx=%d, Last frame time = %.6f "
"send PUSCH time = %.6f TA: %.1f us\n",
SRSLTE_SF_LEN_PRB(cell.nof_prb), sfn, ra_pusch.rv_idx,
srslte_timestamp_real(&uhd_time),
srslte_timestamp_real(&next_tx_time), time_adv_sec*1000000);
cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
//cuhd_start_rx_stream(uhd);
state = RECV_CONNSETUP;
conn_setup_trial = 0;
}
}
@ -590,41 +548,6 @@ int main(int argc, char **argv) {
}
}
}
#else
ra_pusch.mcs.mod = SRSLTE_MOD_QPSK;
ra_pusch.mcs.tbs = 94;
ra_pusch.rv_idx = 0;
ra_pusch.prb_alloc.freq_hopping = 0;
ra_pusch.prb_alloc.L_prb = 4;
ra_pusch.prb_alloc.n_prb[0] = 19;
ra_pusch.prb_alloc.n_prb[1] = 19;
uint32_t ul_sf_idx = 4;
printf("L: %d\n", ra_pusch.prb_alloc.L_prb);
// srslte_ue_ul_set_cfo(&ue_ul, srslte_sync_get_cfo(&ue_sync.strack));
srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs);
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_pusch, data, ul_sf_idx, 111, ul_signal);
if (n < 0) {
fprintf(stderr, "Error encoding PUSCH\n");
exit(-1);
}
srslte_vec_save_file("srslte_pusch_tx", ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb)*sizeof(cf_t));
#ifdef use_usrp
cuhd_recv_with_time(uhd, dummy, 4, 1, &uhd_time.full_secs, &uhd_time.frac_secs);
srslte_timestamp_copy(&next_tx_time, &uhd_time);
while(1) {
srslte_timestamp_add(&next_tx_time, 0, 0.002); // send every 2 ms
cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
}
#else
exit(-1);
#endif
#endif
break;
case RECV_CONNSETUP:
@ -641,6 +564,7 @@ int main(int argc, char **argv) {
} else if (n > 0) {
printf("Received ConnectionSetup len: %d.\n", n);
srslte_vec_fprint_hex(stdout, data_rx, n);
exit(0);
} else {
conn_setup_trial++;
if (conn_setup_trial == 20) {

@ -40,6 +40,7 @@ namespace srslte {
class SRSLTE_API radio
{
public:
virtual void get_time(srslte_timestamp_t *now) = 0;
virtual bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) = 0;
virtual bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time) = 0;
virtual bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time) = 0;

@ -41,7 +41,7 @@
#include "srslte/mimo/precoding.h"
#include "srslte/mimo/layermap.h"
#include "srslte/modem/mod.h"
#include "srslte/modem/demod_hard.h"
#include "srslte/modem/demod_soft.h"
#include "srslte/scrambling/scrambling.h"
#include "regs.h"
@ -59,11 +59,6 @@
#define SRSLTE_PHICH_NORM_NSF 4
#define SRSLTE_PHICH_EXT_NSF 2
typedef struct SRSLTE_API {
uint32_t ngroup;
uint32_t nseq;
}srslte_phich_alloc_t;
/* phich object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
@ -81,10 +76,11 @@ typedef struct SRSLTE_API {
/* bit message */
uint8_t data[SRSLTE_PHICH_NBITS];
float data_rx[SRSLTE_PHICH_NBITS];
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_demod_hard_t demod;
srslte_demod_soft_t demod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_precoding_t precoding;
@ -104,7 +100,7 @@ SRSLTE_API int srslte_phich_decode(srslte_phich_t *q,
uint32_t nseq,
uint32_t nsubframe,
uint8_t *ack,
uint32_t *distance);
float *distance);
SRSLTE_API int srslte_phich_encode(srslte_phich_t *q,
uint8_t ack,
@ -118,4 +114,6 @@ SRSLTE_API void srslte_phich_reset(srslte_phich_t *q,
SRSLTE_API uint32_t srslte_phich_ngroups(srslte_phich_t *q);
SRSLTE_API uint32_t srslte_phich_nsf(srslte_phich_t *q);
#endif // PHICH_

@ -130,6 +130,8 @@ typedef struct SRSLTE_API {
srslte_ra_mcs_t mcs;
uint32_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation
// than before (SRSLTE_DCI_FORMAT0 message, see also 8.6.1 in 36.2313).
uint32_t n_dmrs;
bool ndi;
bool cqi_request;

@ -137,6 +137,9 @@ SRSLTE_API int srslte_sync_get_cell_id(srslte_sync_t *q);
/* Gets the CFO estimation from the last call to synch_run() */
SRSLTE_API float srslte_sync_get_cfo(srslte_sync_t *q);
/* Sets known CFO to avoid long transients due to average */
SRSLTE_API void srslte_sync_set_cfo(srslte_sync_t *q, float cfo);
/* Gets the CP length estimation from the last call to synch_run() */
SRSLTE_API srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q);

@ -73,6 +73,7 @@ typedef struct SRSLTE_API {
float peak;
float mode;
float psr;
float cfo;
} srslte_ue_cellsearch_result_t;

@ -39,6 +39,8 @@
#ifndef UEDL_H
#define UEDL_H
#include <stdbool.h>
#include "srslte/ch_estimation/chest_dl.h"
#include "srslte/dft/ofdm.h"
#include "srslte/common/phy_common.h"
@ -62,6 +64,7 @@ typedef struct SRSLTE_API {
srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_phich_t phich;
srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES];
srslte_regs_t regs;
srslte_ofdm_t fft;
@ -132,6 +135,11 @@ SRSLTE_API int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t * q,
uint16_t rnti,
uint32_t rvidx);
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t n_prb_lowest,
uint32_t n_dmrs);
SRSLTE_API void srslte_ue_dl_reset(srslte_ue_dl_t *q);
SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q,

@ -112,7 +112,7 @@ public:
dl_buffer(srslte_cell_t cell);
sched_grant get_ul_grant(pdcch_ul_search_t mode, uint32_t rnti);
sched_grant get_dl_grant(pdcch_dl_search_t mode, uint32_t rnti);
bool decode_phich(srslte_phich_alloc_t assignment);
bool decode_phich(sched_grant pusch_grant);
bool decode_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO
private:
srslte_ue_dl_t ue_dl;

@ -128,6 +128,9 @@ SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q,
cf_t **sf_symbols);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo);
SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q);
SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q,

@ -59,6 +59,7 @@ typedef struct SRSLTE_API {
srslte_cell_t cell;
bool normalize_en;
bool cfo_en;
float current_cfo;
@ -83,6 +84,9 @@ SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
float cur_cfo);
SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q,
bool enabled);
SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,
bool enabled);

@ -66,7 +66,7 @@ namespace ue {
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time);
bool get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant);
bool get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant);
bool decode_phich(srslte_phich_alloc_t assignment);
bool decode_phich(srslte::ue::sched_grant pusch_grant);
bool decode_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO
private:
params *params_db;

@ -75,6 +75,9 @@ public:
// Indicate the PHY to send PRACH as soon as possible
bool send_prach(uint32_t preamble_idx);
// Returns TTI when PRACH was transmitted. -1 if not yet transmitted
int get_prach_transmitted_tti();
// Get handler to the radio
radio* get_radio();
@ -125,12 +128,15 @@ private:
pthread_t phy_thread;
float time_adv_sec;
uint32_t n_ta;
bool radio_is_streaming;
srslte_timestamp_t last_rx_time;
float cellsearch_cfo;
static void *phy_thread_fnc(void *arg);
bool decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]);
int sync_sfn();
void run_rx_tx_state();
bool init_radio_handler(char *args);
ul_buffer* get_ul_buffer_adv(uint32_t tti);
};
}

@ -26,6 +26,7 @@
*/
#include "srslte/srslte.h"
#include "srslte/common/radio.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/ue_itf/params.h"
@ -41,7 +42,8 @@ namespace ue {
void free_cell();
bool prepare_to_send(uint32_t preamble_idx);
bool is_ready_to_send(uint32_t current_tti);
bool send(void *radio_handler, srslte_timestamp_t rx_time);
int get_transmitted_tti();
bool send(srslte::radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
private:
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
params *params_db = NULL;
@ -50,6 +52,10 @@ namespace ue {
uint32_t len;
cf_t *buffer[64];
srslte_prach_t prach;
uint32_t transmitted_tti;
srslte_cell_t cell;
cf_t *signal_buffer;
srslte_cfo_t cfo_h;
};
}

@ -50,11 +50,14 @@ namespace ue {
bool is_downlink();
void* get_grant_ptr();
uint32_t get_tbs();
uint32_t get_current_tx_nb();
void set_current_tx_nb(uint32_t current_tx_nb);
protected:
union {
srslte_ra_pusch_t ul_grant;
srslte_ra_pdsch_t dl_grant;
};
uint32_t current_tx_nb;
direction_t dir;
uint16_t rnti;
};

@ -51,7 +51,7 @@ namespace ue {
bool generate_pusch(sched_grant pusch_grant, uint8_t *payload);
bool generate_pusch(sched_grant pusch_grant, uint8_t *payload, srslte_uci_data_t uci_data);
bool generate_pucch(srslte_uci_data_t uci_data);
bool send_packet(radio* radio_handler, float time_adv_sec, srslte_timestamp_t rx_time);
bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time);
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
private:

@ -92,8 +92,10 @@ int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti,
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Unsupported message type: ");
srslte_dci_msg_type_fprint(stderr, type);
if (SRSLTE_VERBOSE_ISINFO()) {
fprintf(stderr, "Unsupported message type: ");
srslte_dci_msg_type_fprint(stderr, type);
}
}
}
return ret;
@ -375,9 +377,10 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t
data->ndi = *y++ ? true : false;
// TCP and DM RS commands not implemented
// TPC and DM RS commands not implemented
y += 5;
data->n_dmrs = 0;
// CQI request
data->cqi_request = *y++ ? true : false;

@ -53,6 +53,14 @@ uint32_t srslte_phich_ngroups(srslte_phich_t *q) {
return srslte_regs_phich_ngroups(q->regs);
}
uint32_t srslte_phich_nsf(srslte_phich_t *q) {
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
return SRSLTE_PHICH_NORM_NSF;
} else {
return SRSLTE_PHICH_EXT_NSF;
}
}
void srslte_phich_reset(srslte_phich_t *q, cf_t *slot_symbols[SRSLTE_MAX_PORTS]) {
int i;
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
@ -79,12 +87,13 @@ int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell
fprintf(stderr, "Error initializing precoding\n");
}
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK, false)) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK, true)) {
goto clean;
}
srslte_demod_hard_init(&q->demod);
srslte_demod_hard_table_set(&q->demod, SRSLTE_MOD_BPSK);
srslte_demod_soft_init(&q->demod, SRSLTE_PHICH_MAX_NSYMB);
srslte_demod_soft_table_set(&q->demod, &q->mod);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
@ -114,25 +123,29 @@ void srslte_phich_free(srslte_phich_t *q) {
/* Decodes ACK
*
*/
uint8_t srslte_phich_ack_decode(uint8_t bits[SRSLTE_PHICH_NBITS], uint32_t *distance) {
int i, n;
n = 0;
for (i = 0; i < SRSLTE_PHICH_NBITS; i++) {
n += bits[i];
uint8_t srslte_phich_ack_decode(float bits[SRSLTE_PHICH_NBITS], float *distance) {
int i;
float ack_table[2][3] = {{-1.0, -1.0, -1.0}, {1.0, 1.0, 1.0}};
float max_corr = -9999;
uint8_t index=0;
if (SRSLTE_VERBOSE_ISINFO()) {
INFO("Received bits: ", 0);
srslte_vec_fprint_f(stdout, bits, SRSLTE_PHICH_NBITS);
}
INFO("PHICH decoder: %d, %d, %d\n", bits[0], bits[1], bits[2]);
if (n >= 2) {
if (distance) {
*distance = 3 - n;
}
return 1;
} else {
if (distance) {
*distance = n;
for (i = 0; i < 2; i++) {
float corr = srslte_vec_dot_prod_fff(ack_table[i], bits, SRSLTE_PHICH_NBITS);
INFO("Corr%d=%f\n", i, corr);
if (corr > max_corr) {
max_corr = corr;
if (distance) {
*distance = max_corr;
}
index = i;
}
return 0;
}
}
return index;
}
/** Encodes the ACK
@ -147,7 +160,7 @@ void srslte_phich_ack_encode(uint8_t ack, uint8_t bits[SRSLTE_PHICH_NBITS]) {
* Returns 1 if successfully decoded the CFI, 0 if not and -1 on error
*/
int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, uint32_t *distance) {
uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, float *distance) {
/* Set pointers for layermapping & precoding */
int i, j;
@ -265,10 +278,10 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_M
if (SRSLTE_VERBOSE_ISDEBUG())
srslte_vec_fprint_c(stdout, q->z, SRSLTE_PHICH_NBITS);
srslte_demod_hard_demodulate(&q->demod, q->z, q->data, SRSLTE_PHICH_NBITS);
srslte_demod_soft_demodulate(&q->demod, q->z, q->data_rx, SRSLTE_PHICH_NBITS);
if (ack) {
*ack = srslte_phich_ack_decode(q->data, distance);
*ack = srslte_phich_ack_decode(q->data_rx, distance);
}
return SRSLTE_SUCCESS;

@ -44,6 +44,7 @@
#define PHI_4 2 // PRACH phi parameter for format 4
#define MAX_ROOTS 838 // Max number of root sequences
#define PRACH_AMP 0.5
/******************************************************
* Reference tables from 3GPP TS 36.211 v10.7.0
@ -357,14 +358,14 @@ int srslte_prach_init(srslte_prach_t *p,
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(p->zc_fft, false);
srslte_dft_plan_set_norm(p->zc_fft, false);
srslte_dft_plan_set_norm(p->zc_fft, true);
p->zc_ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
if(srslte_dft_plan(p->zc_ifft, p->N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(p->zc_ifft, false);
srslte_dft_plan_set_norm(p->zc_ifft, false);
srslte_dft_plan_set_norm(p->zc_ifft, true);
// Generate our 64 sequences
p->N_roots = 0;
@ -437,7 +438,7 @@ int srslte_prach_gen(srslte_prach_t *p,
// Copy preamble sequence into buffer
for(int i=0;i<p->N_seq;i++){
signal[p->N_cp+i] = p->ifft_out[i%p->N_ifft_prach];
signal[p->N_cp+i] = PRACH_AMP*p->ifft_out[i%p->N_ifft_prach];
}
ret = SRSLTE_SUCCESS;

@ -214,7 +214,7 @@ void base_free() {
}
int main(int argc, char **argv) {
uint32_t distance;
float distance;
int n;
uint32_t ngroup, nseq, max_nseq;
uint8_t ack_rx;

@ -108,7 +108,8 @@ int main(int argc, char **argv) {
int nof_re;
cf_t *slot_symbols[SRSLTE_MAX_PORTS];
uint8_t ack[50][SRSLTE_PHICH_NORM_NSEQUENCES], ack_rx;
uint32_t nsf, distance;
uint32_t nsf;
float distance;
int cid, max_cid;
uint32_t ngroup, nseq, max_nseq;

@ -144,6 +144,10 @@ float srslte_sync_get_cfo(srslte_sync_t *q) {
return q->mean_cfo;
}
void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) {
q->mean_cfo = cfo;
}
float srslte_sync_get_last_peak_value(srslte_sync_t *q) {
return q->peak_value;
}
@ -313,7 +317,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
// Make sure we have enough space to estimate CFO
if (peak_pos + find_offset >= q->fft_size) {
float cfo = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset+peak_pos-q->fft_size]);
/* compute cumulative moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, CFO_EMA_ALPHA);
} else {

@ -175,6 +175,9 @@ static void get_cell(srslte_ue_cellsearch_t * q, uint32_t nof_detected_frames, s
// PSR is already averaged so take the last value
found_cell->psr = q->candidates[nof_detected_frames-1].psr;
// CFO is also already averaged
found_cell->cfo = q->candidates[nof_detected_frames-1].cfo;
}
/** Finds up to 3 cells, one per each N_id_2=0,1,2 and stores ID and CP in the structure pointed by found_cell.
@ -235,6 +238,7 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q, uint32_t N_id_2
q->candidates[nof_detected_frames].cp = srslte_sync_get_cp(&q->ue_sync.strack);
q->candidates[nof_detected_frames].peak = q->ue_sync.strack.pss.peak_value;
q->candidates[nof_detected_frames].psr = srslte_sync_get_peak_value(&q->ue_sync.strack);
q->candidates[nof_detected_frames].cfo = srslte_ue_sync_get_cfo(&q->ue_sync);
INFO
("CELL SEARCH: [%3d/%3d/%d]: Found peak PSR=%.3f, Cell_id: %d CP: %s\n",
nof_detected_frames, nof_scanned_frames, q->nof_frames_to_scan,

@ -70,6 +70,10 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit;
}
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PHICH object\n");
goto clean_exit;
}
if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
@ -118,6 +122,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
srslte_chest_dl_free(&q->chest);
srslte_regs_free(&q->regs);
srslte_pcfich_free(&q->pcfich);
srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch);
srslte_pdsch_free(&q->pdsch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
@ -312,3 +317,29 @@ int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, u
return 0;
}
}
/* Computes n_group and n_seq according to Section 9.1.2 in 36.213 and calls phich processing function */
bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, uint32_t n_dmrs)
{
uint8_t ack_bit;
float distance;
uint32_t Ngroups = srslte_phich_ngroups(&q->phich);
uint32_t ngroup = (n_prb_lowest+n_dmrs)%Ngroups;
uint32_t nseq = ((n_prb_lowest/Ngroups)+n_dmrs)%(2*srslte_phich_nsf(&q->phich));
INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d\n",
sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq);
if (!srslte_phich_decode(&q->phich, q->sf_symbols, q->ce, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) {
INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance);
} else {
fprintf(stderr, "Error decoding PHICH\n");
return false;
}
if (ack_bit && distance > 5.0) {
return true;
} else {
return false;
}
}

@ -221,6 +221,10 @@ float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) {
return 15000 * srslte_sync_get_cfo(&q->strack);
}
void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
srslte_sync_set_cfo(&q->strack, cfo/15000);
}
float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) {
return 5000*q->mean_time_offset;
}
@ -266,9 +270,6 @@ static int find_peak_ok(srslte_ue_sync_t *q) {
q->frame_find_cnt = 0;
q->mean_time_offset = 0;
/* Set tracking CFO average to find CFO */
q->strack.mean_cfo = q->sfind.mean_cfo;
/* Goto Tracking state */
q->state = SF_TRACK;
}
@ -455,13 +456,6 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
-srslte_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;

@ -128,6 +128,11 @@ void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) {
q->current_cfo = cur_cfo;
}
void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q, bool enabled)
{
q->cfo_en = enabled;
}
void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled)
{
q->normalize_en = enabled;
@ -194,7 +199,7 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_
fprintf(stderr, "Error configuring HARQ process\n");
return ret;
}
printf("sf_idx: %d, rnti: %d\n", sf_idx, rnti);
if (srslte_pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
return ret;
@ -214,7 +219,9 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
//srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
}
if (q->normalize_en) {
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(q->harq_process[0].ul_alloc.L_prb);

@ -65,20 +65,20 @@ void dl_buffer::free_cell()
// FIXME: Avoid this memcpy modifying ue_sync to directly write into provided pointer
bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time)
{
bool ret = false;
if (signal_buffer) {
INFO("DL Buffer TTI %d: Receiving packet\n", tti);
cf_t *sf_buffer = NULL;
sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false;
if (srslte_ue_sync_get_buffer(ue_sync, &sf_buffer) == 1) {
memcpy(signal_buffer, sf_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ue_sync_get_last_timestamp(ue_sync, rx_time);
sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false;
ready();
return true;
} else {
return false;
}
ret = true;
}
srslte_ue_sync_get_last_timestamp(ue_sync, rx_time);
}
return ret;
}
bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant)
@ -154,7 +154,7 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant)
}
}
bool dl_buffer::decode_phich(srslte_phich_alloc_t assignment)
bool dl_buffer::decode_phich(sched_grant pusch_grant)
{
if (signal_buffer && is_ready()) {
if (!sf_symbols_and_ce_done) {
@ -163,7 +163,10 @@ bool dl_buffer::decode_phich(srslte_phich_alloc_t assignment)
}
sf_symbols_and_ce_done = true;
}
return false;
srslte_ra_pusch_t *ra_ul = (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr();
return srslte_ue_dl_decode_phich(&ue_dl, tti%10, ra_ul->prb_alloc.n_prb[0], ra_ul->n_dmrs);
}
}

@ -53,12 +53,19 @@ bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_)
params_db.set_param(params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160);
params_db.set_param(params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100);
if (!pthread_create(&phy_thread, NULL, phy_thread_fnc, this)) {
pthread_attr_t attr;
struct sched_param param;
param.sched_priority = 99;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
if (!pthread_create(&phy_thread, &attr, phy_thread_fnc, this)) {
started = true;
} else {
perror("pthread_create");
}
pthread_attr_destroy(&attr);
return started;
}
@ -120,6 +127,11 @@ bool phy::send_prach(uint32_t preamble_idx)
return false;
}
int phy::get_prach_transmitted_tti()
{
return prach_buffer.get_transmitted_tti();
}
// Do fast measurement on RSSI and/or PSS autocorrelation energy or PSR
bool phy::measure()
{
@ -134,11 +146,9 @@ bool phy::start_rxtx()
if (phy_state == IDLE) {
if (cell_is_set) {
// Set RX/TX sampling rate
radio_handler->set_rx_srate(srslte_sampling_freq_hz(cell.nof_prb));
radio_handler->set_tx_srate(srslte_sampling_freq_hz(cell.nof_prb));
radio_handler->set_rx_srate((float) srslte_sampling_freq_hz(cell.nof_prb));
radio_handler->set_tx_srate((float) srslte_sampling_freq_hz(cell.nof_prb));
// Start streaming
radio_handler->start_rx();
phy_state = RXTX;
return true;
} else {
@ -202,6 +212,8 @@ bool phy::set_cell(srslte_cell_t cell_) {
{
if (!srslte_ue_sync_init(&ue_sync, cell, radio_recv_wrapper_cs, radio_handler))
{
srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo);
if (prach_buffer.init_cell(cell, &params_db)) {
for(uint32_t i=0;i<6;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->init_cell(cell, &params_db);
@ -226,7 +238,12 @@ bool phy::set_cell(srslte_cell_t cell_) {
ul_buffer* phy::get_ul_buffer(uint32_t tti)
{
return (ul_buffer*) ul_buffer_queue->get(tti - ul_buffer::tx_advance_sf);
return (ul_buffer*) ul_buffer_queue->get(tti);
}
ul_buffer* phy::get_ul_buffer_adv(uint32_t tti)
{
return (ul_buffer*) ul_buffer_queue->get(tti + ul_buffer::tx_advance_sf);
}
dl_buffer* phy::get_dl_buffer(uint32_t tti)
@ -284,8 +301,9 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b
// Save result
cell_ptr->id = found_cells[max_peak_cell].cell_id;
cell_ptr->cp = found_cells[max_peak_cell].cp;
cellsearch_cfo = found_cells[max_peak_cell].cfo;
INFO("\nFound CELL ID: %d CP: %s\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp));
INFO("\nFound CELL ID: %d CP: %s, CFO: %f\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp), cellsearch_cfo);
srslte_ue_mib_sync_t ue_mib_sync;
@ -351,6 +369,12 @@ void phy::run_rx_tx_state()
{
int ret;
if (!is_sfn_synched) {
if (!radio_is_streaming) {
// Start streaming
radio_handler->start_rx();
radio_is_streaming = true;
}
ret = sync_sfn();
switch(ret) {
default:
@ -364,20 +388,24 @@ void phy::run_rx_tx_state()
}
} else {
uint32_t current_tti = ttisync->get_producer_cntr();
// Receive alligned buffer for the current tti
srslte_timestamp_t rx_time;
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &rx_time);
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
// Prepare transmission for the next tti
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
// send prach if we have to
if (prach_buffer.is_ready_to_send(current_tti)) {
prach_buffer.send(radio_handler, rx_time);
prach_buffer.send(radio_handler, cfo, last_rx_time);
}
// send ul buffer if we have to
if (get_ul_buffer(current_tti)->is_released()) {
get_ul_buffer(current_tti)->send_packet(radio_handler, time_adv_sec, rx_time);
if (get_ul_buffer_adv(current_tti)->is_released()) {
get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time);
}
ttisync->increase();
// Receive alligned buffer for the current tti
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time);
ttisync->increase();
}
}

@ -47,12 +47,17 @@ void prach::free_cell()
free(buffer[i]);
}
}
if (signal_buffer) {
free(signal_buffer);
}
srslte_cfo_free(&cfo_h);
srslte_prach_free(&prach);
}
}
bool prach::init_cell(srslte_cell_t cell, params *params_db_)
bool prach::init_cell(srslte_cell_t cell_, params *params_db_)
{
cell = cell_;
params_db = params_db_;
preamble_idx = -1;
if (srslte_prach_init(&prach, srslte_symbol_sz(cell.nof_prb),
@ -73,14 +78,18 @@ bool prach::init_cell(srslte_cell_t cell, params *params_db_)
return false;
}
}
initiated = true;
return true;
srslte_cfo_init(&cfo_h, len);
signal_buffer = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t));
initiated = signal_buffer?true:false;
transmitted_tti = -1;
return initiated;
}
bool prach::prepare_to_send(uint32_t preamble_idx_)
{
if (initiated && preamble_idx_ < 64) {
preamble_idx = preamble_idx_;
transmitted_tti = -1;
INFO("PRACH Buffer: Prepare to send preamble %d\n", preamble_idx);
return true;
} else {
@ -91,7 +100,7 @@ bool prach::prepare_to_send(uint32_t preamble_idx_)
bool prach::is_ready_to_send(uint32_t current_tti_) {
if (initiated && preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) {
// consider the number of subframes the transmission must be anticipated
uint32_t current_tti = current_tti_ + tx_advance_sf;
uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240;
// Get SFN and sf_idx from the PRACH configuration index
uint32_t config_idx = (uint32_t) params_db->get_param(params::PRACH_CONFIG_INDEX);
@ -104,7 +113,8 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
srslte_prach_sf_config(config_idx, &sf_config);
for (int i=0;i<sf_config.nof_sf;i++) {
if ((current_tti%10) == sf_config.sf[i]) {
INFO("PRACH Buffer: Ready to send at tti: %d\n", current_tti);
INFO("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
transmitted_tti = current_tti;
return true;
}
}
@ -114,15 +124,29 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
return false;
}
bool prach::send(void *radio_handler, srslte_timestamp_t rx_time)
int prach::get_transmitted_tti() {
if (initiated) {
return transmitted_tti;
} else {
return -1;
}
}
bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time)
{
// advance transmission time
srslte_timestamp_t tx_time;
srslte_timestamp_copy(&tx_time, &rx_time);
srslte_timestamp_add(&tx_time, 0, 1e-3*tx_advance_sf);
// Correct CFO before transmission
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 1.7*cfo / srslte_symbol_sz(cell.nof_prb));
// transmit
cuhd_send_timed(radio_handler, buffer[preamble_idx], len, tx_time.full_secs, tx_time.frac_secs);
radio_handler->tx(signal_buffer, len, tx_time);
INFO("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n", cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs);
//srslte_vec_save_file("prach", buffer[preamble_idx], len*sizeof(cf_t));
preamble_idx = -1;
}
} // namespace ue

@ -61,6 +61,17 @@ namespace ue {
return dl_grant.mcs.tbs;
}
}
uint32_t sched_grant::get_current_tx_nb()
{
return current_tx_nb;
}
void sched_grant::set_current_tx_nb(uint32_t current_tx_nb_)
{
current_tx_nb = current_tx_nb_;
}
void sched_grant::set_rv(uint32_t rv) {
if (dir == UPLINK) {

@ -38,13 +38,14 @@
namespace srslte {
namespace ue {
bool ul_buffer::init_cell(srslte_cell_t cell_, params *params_db) {
bool ul_buffer::init_cell(srslte_cell_t cell_, params *params_db_) {
cell = cell_;
params_db = params_db;
params_db = params_db_;
current_tx_nb = 0;
if (!srslte_ue_ul_init(&ue_ul, cell)) {
signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
cell_initiated = signal_buffer?true:false;
srslte_ue_ul_set_cfo_enable(&ue_ul, false);
return cell_initiated;
} else {
return false;
@ -69,8 +70,8 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant,
}
bool ul_buffer::generate_pusch(sched_grant pusch_grant,
uint8_t *payload,
srslte_uci_data_t uci_data)
uint8_t *payload,
srslte_uci_data_t uci_data)
{
if (is_ready()) {
if (!pusch_grant.is_uplink()) {
@ -93,13 +94,13 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant,
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = current_tx_nb;
pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb();
srslte_ue_ul_set_pusch_cfg(&ue_ul, &drms_cfg, &pusch_hopping);
int n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(),
payload, uci_data,
(tti+tx_advance_sf)%10, pusch_grant.get_rnti(),
tti%10, pusch_grant.get_rnti(),
signal_buffer);
if (n < 0) {
fprintf(stderr, "Error in UL buffer: Error encoding PUSCH\n");
@ -119,17 +120,23 @@ bool ul_buffer::generate_pucch(srslte_uci_data_t uci_data)
return false;
}
bool ul_buffer::send_packet(radio *radio_handler, float time_adv_sec, srslte_timestamp_t rx_time)
bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time)
{
// send packet through usrp
srslte_timestamp_t tx_time;
srslte_timestamp_copy(&tx_time, &rx_time);
srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec);
INFO("Send PUSCH rx_time= %.6f tx_time = %.6f TA: %.1f us\n",
INFO("Send PUSCH TTI: %d, CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us\n",
tti, cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb),
srslte_timestamp_real(&rx_time),
srslte_timestamp_real(&tx_time), time_adv_sec*1000000);
// Correct CFO before transmission
srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb));
radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time);
//srslte_vec_save_file("pusch", signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)*sizeof(cf_t));
ready();
}

@ -40,26 +40,31 @@ typedef struct {
float uhd_tx_freq;
float uhd_rx_gain;
float uhd_tx_gain;
bool continous;
}prog_args_t;
prog_args_t prog_args;
void args_default(prog_args_t *args) {
args->uhd_rx_freq = -1.0;
args->uhd_tx_freq = -1.0;
args->uhd_rx_gain = 60.0;
args->uhd_tx_gain = 40.0;
args->continous = false;
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [gGv] -f rx_frequency -F tx_frequency (in Hz)\n", prog);
printf("Usage: %s [gGcv] -f rx_frequency -F tx_frequency (in Hz)\n", prog);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_rx_gain);
printf("\t-G UHD TX gain [Default %.2f dB]\n", args->uhd_tx_gain);
printf("\t-c Run continuously [Default only once]\n");
printf("\t-v [increase verbosity, default none]\n");
}
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "gGfFv")) != -1) {
while ((opt = getopt(argc, argv, "gGfFcv")) != -1) {
switch (opt) {
case 'g':
args->uhd_rx_gain = atof(argv[optind]);
@ -73,6 +78,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'F':
args->uhd_tx_freq = atof(argv[optind]);
break;
case 'c':
args->continous = true;
break;
case 'v':
srslte_verbose++;
break;
@ -182,16 +190,19 @@ int rar_unpack(uint8_t *buffer, rar_msg_t *msg)
srslte::ue::phy phy;
uint8_t payload[1024];
uint8_t payload[102400];
const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00};
enum mac_state {RA, RAR, CONNSETUP} state = RA;
uint32_t ra_tti = 0, conreq_tti = 0;
uint32_t preamble_idx = 0;
uint32_t conreq_tti = 0;
uint32_t preamble_idx = 7;
rar_msg_t rar_msg;
uint32_t nof_rx_connsetup = 0, nof_rx_rar = 0, nof_tx_ra = 0;
uint32_t nof_rtx_connsetup = 0;
uint32_t rv_value[4] = {0, 2, 3, 1};
void config_phy() {
phy.set_param(srslte::ue::params::PRACH_CONFIG_INDEX, 0);
phy.set_param(srslte::ue::params::PRACH_FREQ_OFFSET, 0);
@ -207,6 +218,14 @@ void config_phy() {
}
uint32_t interval(uint32_t x1, uint32_t x2) {
if (x1 > x2) {
return x1-x2;
} else {
return 10240-x2+x1;
}
}
// This is the MAC implementation
void run_tti(uint32_t tti) {
INFO("MAC running tti: %d\n", tti);
@ -214,15 +233,12 @@ void run_tti(uint32_t tti) {
// Get buffer
srslte::ue::dl_buffer *dl_buffer = phy.get_dl_buffer(tti);
if (dl_buffer) {
fprintf(stderr, "Error getting DL buffer for tti %d\n", tti);
return;
}
if (state == RA) {
if (nof_tx_ra > 0 && !prog_args.continous) {
exit(0);
}
// Indicate PHY to transmit the PRACH when possible
if (phy.send_prach(preamble_idx)) {
ra_tti = tti;
nof_tx_ra++;
state = RAR;
} else {
@ -231,84 +247,139 @@ void run_tti(uint32_t tti) {
}
} else if (state == RAR) {
srslte::ue::sched_grant rar_grant(srslte::ue::sched_grant::DOWNLINK, 2);
// Assume the maximum RA-window
uint32_t interval = (tti-ra_tti)%10240;
if (interval >= 3 && interval <= 13) {
// Get DL grant for RA-RNTI=2
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant))
{
// Decode packet
if (dl_buffer->decode_pdsch(rar_grant, payload)) {
INFO("RAR received tti: %d\n", tti);
rar_unpack(payload, &rar_msg);
INFO("Received RAR for preamble %d\n", rar_msg.RAPID);
if (rar_msg.RAPID == preamble_idx) {
nof_rx_rar++;
if (SRSLTE_VERBOSE_ISINFO()) {
rar_msg_fprint(stdout, &rar_msg);
}
// Set time advance
phy.set_timeadv_rar(rar_msg.timing_adv_cmd);
// Generate Msg3 grant
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant);
// Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs());
// Get UL buffer
srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+6);
// Generate PUSCH
if (ul_buffer) {
ul_buffer->generate_pusch(connreq_grant, payload);
// Save transmission time
conreq_tti = tti;
state = CONNSETUP;
} else {
fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti);
state = RA;
}
}
}
}
int ra_tti = phy.get_prach_transmitted_tti();
if (ra_tti > 0) {
INFO("PRACH was transmitted at %d\n", ra_tti);
// Assume the maximum RA-window
uint32_t interval_ra = interval(tti, ra_tti);
INFO("Interval=%u\n", interval_ra);
if (interval_ra >= 3 && interval_ra <= 13) {
// Get DL grant for RA-RNTI=2
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant))
{
// Decode packet
if (dl_buffer->decode_pdsch(rar_grant, payload)) {
INFO("RAR received tti: %d\n", tti);
rar_unpack(payload, &rar_msg);
INFO("Received RAR for preamble %d\n", rar_msg.RAPID);
if (rar_msg.RAPID == preamble_idx) {
INFO("Received RAR at TTI: %d\n", tti);
nof_rx_rar++;
if (SRSLTE_VERBOSE_ISINFO()) {
rar_msg_fprint(stdout, &rar_msg);
}
// Set time advance
phy.set_timeadv_rar(rar_msg.timing_adv_cmd);
// Generate Msg3 grant
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant);
// Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs());
// Get UL buffer
srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+6);
// Generate PUSCH
if (ul_buffer) {
connreq_grant.set_rv(0);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti);
//ul_buffer->generate_pusch(connreq_grant, payload);
// Save transmission time
conreq_tti = ul_buffer->tti;
state = CONNSETUP;
} else {
fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti);
state = RA;
}
}
}
}
} else if (interval_ra > 13 && interval_ra < 100) { // avoid wrapping
INFO("RAR not received at TTI=%d (interval_ra=%d)\n", tti, interval_ra);
state = RA;
}
}
} else {
srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti);
if ((tti - conreq_tti)%10240 == 4) {
// Get DL grant for RA-RNTI=2
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
{
// Decode packet
if (dl_buffer->decode_pdsch(conn_setup_grant, payload)) {
INFO("ConnSetup received tti=%d\n", tti);
nof_rx_connsetup++;
uint32_t interval_conreq = interval(tti, conreq_tti);
if (interval_conreq == 4) {
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant);
// Decode PHICH from Connection Request
if (!dl_buffer->decode_phich(connreq_grant)) {
// Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs());
// Get UL buffer
srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+4);
// Generate PUSCH
if (ul_buffer) {
nof_rtx_connsetup++;
if (nof_rtx_connsetup >= 5) {
state = RA;
} else {
connreq_grant.set_current_tx_nb(nof_rtx_connsetup);
connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti);
ul_buffer->generate_pusch(connreq_grant, payload);
// Save transmission time
conreq_tti = ul_buffer->tti;
state = CONNSETUP;
}
} else {
fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti);
state = RA;
}
} else {
// Get DL grant for tmp_rnti
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
{
// Decode packet
if (dl_buffer->decode_pdsch(conn_setup_grant, payload)) {
nof_rx_connsetup++;
state = RA;
nof_rtx_connsetup=0;
if (!prog_args.continous) {
printf("Connection Setup received (%d/%d)\n", nof_rx_connsetup, nof_tx_ra);
}
} else {
INFO("Error decoding PDSCH for Connection Request at TTI=%d\n", tti);
state = RA;
}
} else {
INFO("DCI for Connection Request not found on PDCCH at TTI=%d\n", tti);
state = RA;
}
}
}
}
if (srslte_verbose == SRSLTE_VERBOSE_NONE) {
printf("RECV RAR %.1f \%% RECV ConnSetup %.1f \%% (total RA: %5u) \r",
if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) {
printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r",
(float) 100*nof_rx_rar/nof_tx_ra,
(float) 100*nof_rx_connsetup/nof_tx_ra,
nof_tx_ra);
nof_rx_connsetup, nof_tx_ra);
}
dl_buffer->ready();
}
int main(int argc, char *argv[])
{
srslte_cell_t cell;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
prog_args_t prog_args;
srslte::ue::tti_sync_cv ttisync(10240);
srslte::radio_uhd radio_uhd;

Loading…
Cancel
Save