Merge branch 'next' into mobility

This commit is contained in:
Ismael Gomez 2017-11-07 17:13:57 -08:00
commit 641eceb328
87 changed files with 2073 additions and 659 deletions

View File

@ -249,7 +249,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
@ -257,7 +257,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
@ -271,8 +271,16 @@ int main(int argc, char **argv) {
/* Initialize subframe counter */
sf_cnt = 0;
if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) {
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
if (srslte_ofdm_rx_init(&fft, cell.cp, sf_buffer[0], sf_symbols, cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return -1;
}
@ -284,14 +292,6 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
srslte_rf_start_rx_stream(&rf);
@ -315,7 +315,7 @@ int main(int argc, char **argv) {
case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
return -1;
@ -351,7 +351,7 @@ int main(int argc, char **argv) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
/* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&fft, sf_buffer[0], sf_symbols);
srslte_ofdm_rx_sf(&fft);
srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync));

View File

@ -86,7 +86,7 @@ float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
bool null_file_sink=false;
srslte_filesink_t fsink;
srslte_ofdm_t ifft;
srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft_mbsfn;
srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
@ -311,18 +311,21 @@ void base_init() {
}
/* create ifft object */
if (srslte_ofdm_tx_init(&ifft, SRSLTE_CP_NORM, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
for (i = 0; i < cell.nof_ports; i++) {
if (srslte_ofdm_tx_init(&ifft[i], SRSLTE_CP_NORM, sf_buffer[i], output_buffer[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_normalize(&ifft[i], true);
}
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, sf_buffer[0], output_buffer[0], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2);
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
srslte_ofdm_set_normalize(&ifft, true);
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
@ -413,8 +416,9 @@ void base_free() {
srslte_pmch_free(&pmch);
}
srslte_ofdm_tx_free(&ifft_mbsfn);
srslte_ofdm_tx_free(&ifft);
for (i = 0; i < cell.nof_ports; i++) {
srslte_ofdm_tx_free(&ifft[i]);
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
@ -938,7 +942,8 @@ int main(int argc, char **argv) {
}
/* Configure pmch_cfg parameters */
srslte_ra_dl_grant_t grant;
grant.nof_tb = 1;
grant.tb_en[0] = true;
grant.tb_en[1] = false;
grant.mcs[0].idx = 2;
grant.mcs[0].mod = SRSLTE_MOD_QPSK;
grant.nof_prb = cell.nof_prb;
@ -977,10 +982,10 @@ int main(int argc, char **argv) {
/* Transform to OFDM symbols */
if(sf_idx != 1 || mbsfn_area_id < 0){
for (i = 0; i < cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&ifft, sf_buffer[i], output_buffer[i]);
srslte_ofdm_tx_sf(&ifft[i]);
}
}else{
srslte_ofdm_tx_sf(&ifft_mbsfn, sf_buffer[0], output_buffer[0]);
srslte_ofdm_tx_sf(&ifft_mbsfn);
}
/* send to file or usrp */

View File

@ -510,7 +510,10 @@ int main(int argc, char **argv) {
#endif
}
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
@ -519,7 +522,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
@ -527,10 +530,6 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
@ -632,7 +631,7 @@ int main(int argc, char **argv) {
switch (state) {
case DECODE_MIB:
if (sfidx == 0) {
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
exit(-1);

View File

@ -6435,11 +6435,102 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_from_eutra_command_msg(LIBLTE_BIT_M
Document Reference: 36.331 v10.0.0 Section 6.2.2
*********************************************************************/
// Defines
// Enums
typedef struct{
LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT cell_global_id;
uint16 tracking_area_code;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_identity_list[5];
uint32 n_plmn_identity_list;
bool have_plmn_identity_list;
}LIBLTE_RRC_CGI_INFO_STRUCT;
LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info,
uint8 **ie_ptr);
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr,
LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info);
typedef struct{
uint8 rsrp_result;
bool have_rsrp;
uint8 rsrq_result;
bool have_rsrq;
}LIBLTE_RRC_MEAS_RESULT_STRUCT;
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result,
uint8 **ie_ptr);
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result);
typedef struct{
uint16 phys_cell_id;
LIBLTE_RRC_CGI_INFO_STRUCT cgi_info;
bool have_cgi_info;
LIBLTE_RRC_MEAS_RESULT_STRUCT meas_result;
}LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT;
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra,
uint8 **ie_ptr);
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra);
typedef struct{
//FIXME
}LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT;
typedef struct{
//FIXME
}LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT;
typedef struct{
//FIXME
}LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT;
typedef struct{
LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT result_eutra_list[8];
uint8 n_result;
}LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT;
typedef struct{
LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT result_utra_list[8];
uint8 n_result;
}LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT;
typedef struct{
LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT result_geran_list[8];
uint8 n_result;
}LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT;
typedef struct{
bool pre_registration_status_HRPD;
LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT cdma2000[8];
}LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT;
typedef enum{
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA = 0,
LIBLTE_RRC_MEAS_RESULT_LIST_UTRA,
LIBLTE_RRC_MEAS_RESULT_LIST_GERAN,
LIBLTE_RRC_MEAS_RESULTS_CDMA2000,
LIBLTE_RRC_MEAS_RESULT_N_ITEMS,
}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM;
static const char liblte_rrc_meas_reult_neigh_cells_text[LIBLTE_RRC_MEAS_RESULT_N_ITEMS][32] = { "measResultListEUTRA", "measResultListUTRA", "measResultListGERAN", "measResultsCDMA2000"};
typedef union{
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT eutra;
LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT utra;
LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT geran;
LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT cdma2000;
}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION;
//TODO: pack/unpack for the result lists
// Structs
typedef struct{
// FIXME
uint8 meas_id;
uint8 pcell_rsrp_result;
uint8 pcell_rsrq_result;
LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION meas_result_neigh_cells;
LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM meas_result_neigh_cells_choice;
bool have_meas_result_neigh_cells;
}LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT;
// Functions
LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report,

View File

@ -24,18 +24,20 @@ template<typename metrics_t>
class metrics_listener
{
public:
virtual void set_metrics(metrics_t &m, float report_period_secs=1.0) = 0;
};
virtual void set_metrics(metrics_t &m) = 0;
};
template<typename metrics_t>
class metrics_hub : public periodic_thread
{
public:
metrics_hub() {
m = NULL;
}
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) {
m = m_;
metrics_hub()
:m(NULL)
,report_period_secs(1)
{}
bool init(metrics_interface<metrics_t> *m_, float report_period_secs_=1.0) {
m = m_;
report_period_secs = report_period_secs_;
start_periodic(report_period_secs*1e6);
return true;
}
@ -60,8 +62,8 @@ private:
}
}
metrics_interface<metrics_t> *m;
std::vector<metrics_listener<metrics_t>*> listeners;
std::vector<metrics_listener<metrics_t>*> listeners;
float report_period_secs;
};
} // namespace srslte

View File

@ -80,8 +80,9 @@ typedef struct pcaprec_hdr_s {
#define MAC_LTE_UEID_TAG 0x03
/* 2 bytes, network order */
#define MAC_LTE_SUBFRAME_TAG 0x04
#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04
/* 2 bytes, network order */
/* SFN is stored in 12 MSB and SF in 4 LSB */
#define MAC_LTE_PREDFINED_DATA_TAG 0x05
/* 1 byte */
@ -150,7 +151,7 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context,
pcaprec_hdr_t packet_header;
char context_header[256];
int offset = 0;
unsigned short tmp16;
uint16_t tmp16;
/* Can't write if file wasn't successfully opened */
if (fd == NULL) {
@ -176,9 +177,11 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context,
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* Subframe number */
context_header[offset++] = MAC_LTE_SUBFRAME_TAG;
tmp16 = htons(context->subFrameNumber);
/* Subframe Number and System Frame Number */
/* SFN is stored in 12 MSB and SF in 4 LSB */
context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
tmp16 = (context->sysFrameNumber << 4) | context->subFrameNumber;
tmp16 = htons(tmp16);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
@ -215,4 +218,4 @@ inline void MAC_LTE_PCAP_Close(FILE *fd)
fclose(fd);
}
#endif /* UEPCAP_H */
#endif /* UEPCAP_H */

View File

@ -445,7 +445,8 @@ typedef struct {
float snr_ema_coeff;
std::string snr_estim_alg;
bool cfo_integer_enabled;
float cfo_correct_tol_hz;
float cfo_correct_tol_hz;
float cfo_ema;
int time_correct_period;
bool sfo_correct_disable;
std::string sss_algorithm;

View File

@ -101,8 +101,8 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT)
#define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB)
#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceil((((float) (c)*(symbol_sz))/2048)))
#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) ((symbol==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceilf((((float) (c)*(symbol_sz))/2048.0f)))
#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) (((symbol)==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN))
#define SRSLTE_SLOT_LEN(symbol_sz) (symbol_sz*15/2)
@ -197,7 +197,8 @@ typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0,
SRSLTE_MOD_QPSK,
SRSLTE_MOD_16QAM,
SRSLTE_MOD_64QAM
SRSLTE_MOD_64QAM,
SRSLTE_MOD_LAST
} srslte_mod_t;
typedef struct SRSLTE_API {

View File

@ -63,6 +63,7 @@ typedef struct SRSLTE_API {
void *in; // Input buffer
void *out; // Output buffer
void *p; // DFT plan
bool is_guru;
bool forward; // Forward transform?
bool mirror; // Shift negative and positive frequencies?
bool db; // Provide output in dB?
@ -85,6 +86,17 @@ SRSLTE_API int srslte_dft_plan_c(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir,
cf_t *in_buffer,
cf_t *out_buffer,
int istride,
int ostride,
int how_many,
int idist,
int odist);
SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir);
@ -92,6 +104,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan,
const int new_dft_points);
SRSLTE_API int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan,
const int new_dft_points,
cf_t *in_buffer,
cf_t *out_buffer,
int istride,
int ostride,
int how_many,
int idist,
int odist);
SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan,
int new_dft_points);
@ -129,6 +151,8 @@ SRSLTE_API void srslte_dft_run_c(srslte_dft_plan_t *plan,
cf_t *in,
cf_t *out);
SRSLTE_API void srslte_dft_run_guru_c(srslte_dft_plan_t *plan);
SRSLTE_API void srslte_dft_run_r(srslte_dft_plan_t *plan,
float *in,
float *out);

View File

@ -47,14 +47,18 @@
/* This is common for both directions */
typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan;
srslte_dft_plan_t fft_plan_sf[2];
uint32_t max_prb;
uint32_t nof_symbols;
uint32_t symbol_sz;
uint32_t nof_guards;
uint32_t nof_re;
uint32_t slot_sz;
uint32_t sf_sz;
srslte_cp_t cp;
cf_t *tmp; // for removing zero padding
cf_t *in_buffer;
cf_t *out_buffer;
bool mbsfn_subframe;
uint32_t mbsfn_guard_len;
@ -69,12 +73,16 @@ typedef struct SRSLTE_API{
SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
int symbol_sz,
int nof_prb,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
int symbol_sz,
int nof_prb,
srslte_dft_dir_t dir,
@ -82,12 +90,14 @@ SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
@ -100,39 +110,35 @@ SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q,
int slot_in_sf);
SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q);
SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q,
int slot_in_sf);
SRSLTE_API void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q);
SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q,
float freq_shift);
@ -144,4 +150,4 @@ SRSLTE_API void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q,
uint8_t non_mbsfn_region);
#endif
#endif

View File

@ -68,7 +68,7 @@ typedef struct SRSLTE_API {
cf_t *sf_symbols[SRSLTE_MAX_PORTS];
cf_t *slot1_symbols[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft;
srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
srslte_regs_t regs;
@ -109,7 +109,8 @@ typedef struct {
} srslte_enb_dl_phich_t;
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
cf_t *out_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb);
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
@ -146,8 +147,7 @@ SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t *q,
SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q,
uint32_t tti);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q,
cf_t *signal_buffer);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q);
SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q,
uint16_t rnti);

View File

@ -101,6 +101,7 @@ typedef struct {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
cf_t *in_buffer,
uint32_t max_prb);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);

View File

@ -48,6 +48,7 @@ typedef struct SRSLTE_API {
uint32_t nof_layers;
uint32_t codebook_idx;
srslte_mimo_type_t mimo_type;
bool tb_cw_swap;
} srslte_pdsch_cfg_t;
#endif

View File

@ -103,13 +103,11 @@ typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb;
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
uint32_t Qm2[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb;
srslte_sf_t sf_type;
bool tb_en[SRSLTE_MAX_CODEWORDS];
uint32_t pinfo;
bool tb_cw_swap;
} srslte_ra_dl_grant_t;
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
@ -226,8 +224,7 @@ SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant,
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci,
uint32_t nof_prb,
uint32_t n_rb_ho,
srslte_ra_ul_grant_t *grant,
uint32_t harq_pid);
srslte_ra_ul_grant_t *grant);
SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant,
srslte_cp_t cp,

View File

@ -80,7 +80,7 @@ typedef struct SRSLTE_API {
srslte_pmch_t pmch;
srslte_phich_t phich;
srslte_regs_t regs;
srslte_ofdm_t fft;
srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
srslte_ofdm_t fft_mbsfn;
srslte_chest_dl_t chest;
@ -128,6 +128,7 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb,
uint32_t nof_rx_antennas);

View File

@ -79,6 +79,7 @@ typedef struct SRSLTE_API {
} srslte_ue_mib_t;
SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb);
SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q);
@ -89,7 +90,6 @@ SRSLTE_API int srslte_ue_mib_set_cell(srslte_ue_mib_t * q,
SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q);
SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q,
cf_t *input,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN],
uint32_t *nof_tx_ports,
int *sfn_offset);

View File

@ -185,7 +185,10 @@ SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
float tol);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo);
float cfo);
SRSLTE_API void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q,
float ema);
SRSLTE_API void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q,
bool enable);

View File

@ -108,6 +108,7 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
cf_t *out_buffer,
uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);

View File

@ -33,6 +33,11 @@
#endif
#include <immintrin.h>
#endif /* LV_HAVE_SSE */
#include <stdio.h>
#ifdef HAVE_NEON
#include <arm_neon.h>
#endif
/*
* SSE Macros
@ -121,7 +126,17 @@
#define SRSLTE_SIMD_C16_SIZE 8
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
#define SRSLTE_SIMD_F_SIZE 4
#define SRSLTE_SIMD_CF_SIZE 4
#define SRSLTE_SIMD_I_SIZE 4
#define SRSLTE_SIMD_S_SIZE 8
#define SRSLTE_SIMD_C16_SIZE 8
#else /* LV_HAVE_NEON */
#define SRSLTE_SIMD_F_SIZE 0
#define SRSLTE_SIMD_CF_SIZE 0
@ -130,6 +145,7 @@
#define SRSLTE_SIMD_S_SIZE 0
#define SRSLTE_SIMD_C16_SIZE 0
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -147,6 +163,10 @@ typedef __m256 simd_f_t;
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
typedef __m128 simd_f_t;
#else /* HAVE_NEON */
#ifdef HAVE_NEON
typedef float32x4_t simd_f_t;
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -161,6 +181,10 @@ static inline simd_f_t srslte_simd_f_load(float *ptr) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_load_ps(ptr);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vld1q_f32(ptr);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -170,11 +194,15 @@ static inline simd_f_t srslte_simd_f_loadu(float *ptr) {
#ifdef LV_HAVE_AVX512
return _mm512_loadu_ps(ptr);
#else /* LV_HAVE_AVX512 */
#ifdef LV_HAVE_AVX2
#ifdef LV_HAVE_AVX2
return _mm256_loadu_ps(ptr);
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_loadu_ps(ptr);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vld1q_f32(ptr);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -189,6 +217,10 @@ static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
_mm_store_ps(ptr, simdreg);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
vst1q_f32(ptr, simdreg);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -203,6 +235,10 @@ static inline void srslte_simd_f_storeu(float *ptr, simd_f_t simdreg) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
_mm_storeu_ps(ptr, simdreg);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
vst1q_f32(ptr, simdreg);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -217,6 +253,10 @@ static inline simd_f_t srslte_simd_f_set1(float x) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_set1_ps(x);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vdupq_n_f32(x);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -231,6 +271,10 @@ static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_mul_ps(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vmulq_f32(a,b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -243,8 +287,12 @@ static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) {
#ifdef LV_HAVE_AVX2
return _mm256_rcp_ps(a);
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
#ifdef LV_HAVE_SSE
return _mm_rcp_ps(a);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vmulq_f32(vrecpeq_f32(a), vrecpsq_f32(vrecpeq_f32(a), a));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -260,11 +308,30 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_addsub_ps(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON
float* a_ptr = (float*) &a;
float* b_ptr = (float*) &b;
simd_f_t ret;
float* c_ptr = (float*) &ret;
for(int i = 0; i<4;i++){
if(i%2==0){
c_ptr[i] = a_ptr[i] - b_ptr[i];
}else{
c_ptr[i] = a_ptr[i] + b_ptr[i];
}
}
return ret;
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
}
static inline simd_f_t srslte_simd_f_sub(simd_f_t a, simd_f_t b) {
#ifdef LV_HAVE_AVX512
return _mm512_sub_ps(a, b);
@ -274,6 +341,10 @@ static inline simd_f_t srslte_simd_f_sub(simd_f_t a, simd_f_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_sub_ps(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vsubq_f32(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -286,8 +357,12 @@ static inline simd_f_t srslte_simd_f_add(simd_f_t a, simd_f_t b) {
#ifdef LV_HAVE_AVX2
return _mm256_add_ps(a, b);
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
#ifdef LV_HAVE_SSE
return _mm_add_ps(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vaddq_f32(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -300,8 +375,12 @@ static inline simd_f_t srslte_simd_f_zero (void) {
#ifdef LV_HAVE_AVX2
return _mm256_setzero_ps();
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
#ifdef LV_HAVE_SSE
return _mm_setzero_ps();
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vdupq_n_f32(0);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -316,6 +395,10 @@ static inline simd_f_t srslte_simd_f_swap(simd_f_t a) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_shuffle_ps(a, a, 0b10110001);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vcombine_f32(vrev64_f32(vget_low_f32(a)), vrev64_f32(vget_high_f32(a)));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -344,6 +427,10 @@ static inline simd_f_t srslte_simd_f_hadd(simd_f_t a, simd_f_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_hadd_ps(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vcombine_f32( vpadd_f32( vget_low_f32(a), vget_high_f32(a) ), vpadd_f32( vget_low_f32(b), vget_high_f32(b) ) );
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -358,6 +445,12 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_sqrt_ps(a);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
float32x4_t sqrt_reciprocal = vrsqrteq_f32(a);
sqrt_reciprocal = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a,sqrt_reciprocal), sqrt_reciprocal),sqrt_reciprocal);
return vmulq_f32(a,sqrt_reciprocal);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -368,10 +461,15 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) {
#if SRSLTE_SIMD_CF_SIZE
#ifdef HAVE_NEON
typedef float32x4x2_t simd_cf_t;
#else
typedef struct {
simd_f_t re;
simd_f_t im;
} simd_cf_t;
#endif
/* Complex Single precission Floating point functions */
static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) {
@ -399,6 +497,10 @@ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) {
__m128 i2 = _mm_load_ps((float*)(ptr + 2));
ret.re = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(2,0,2,0));
ret.im = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(3,1,3,1));
#else
#ifdef HAVE_NEON
ret = vld2q_f32((float*)(ptr));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -431,6 +533,10 @@ static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) {
__m128 i2 = _mm_loadu_ps((float*)(ptr + 2));
ret.re = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(2,0,2,0));
ret.im = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(3,1,3,1));
#else
#ifdef HAVE_NEON
ret = vld2q_f32((float*)(ptr));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -450,6 +556,11 @@ static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) {
#ifdef LV_HAVE_SSE
ret.re = _mm_load_ps(re);
ret.im = _mm_load_ps(im);
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
ret.val[0] = vld1q_f32(re);
ret.val[1] = vld1q_f32(im);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -469,6 +580,11 @@ static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) {
#ifdef LV_HAVE_SSE
ret.re = _mm_loadu_ps(re);
ret.im = _mm_loadu_ps(im);
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
ret.val[0] = vld1q_f32(re);
ret.val[1] = vld1q_f32(im);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -497,6 +613,10 @@ static inline void srslte_simd_cfi_store(cf_t *ptr, simd_cf_t simdreg) {
#ifdef LV_HAVE_SSE
_mm_store_ps((float*)(ptr), _mm_unpacklo_ps(simdreg.re, simdreg.im));
_mm_store_ps((float*)(ptr + 2), _mm_unpackhi_ps(simdreg.re, simdreg.im));
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
vst2q_f32((float*)(ptr), simdreg);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -524,6 +644,10 @@ static inline void srslte_simd_cfi_storeu(cf_t *ptr, simd_cf_t simdreg) {
#ifdef LV_HAVE_SSE
_mm_storeu_ps((float*)(ptr), _mm_unpacklo_ps(simdreg.re, simdreg.im));
_mm_storeu_ps((float*)(ptr + 2), _mm_unpackhi_ps(simdreg.re, simdreg.im));
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
vst2q_f32((float*)(ptr), simdreg);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -541,6 +665,11 @@ static inline void srslte_simd_cf_store(float *re, float *im, simd_cf_t simdreg)
#ifdef LV_HAVE_SSE
_mm_store_ps((float *) re, simdreg.re);
_mm_store_ps((float *) im, simdreg.im);
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
vst1q_f32((float *) re, simdreg.val[0]);
vst1q_f32((float *) im, simdreg.val[1]);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -558,6 +687,11 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg
#ifdef LV_HAVE_SSE
_mm_storeu_ps((float *) re, simdreg.re);
_mm_storeu_ps((float *) im, simdreg.im);
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
vst1q_f32((float *) re, simdreg.val[0]);
vst1q_f32((float *) im, simdreg.val[1]);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -576,6 +710,11 @@ static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) {
#ifdef LV_HAVE_SSE
ret.re = _mm_set1_ps(__real__ x);
ret.im = _mm_set1_ps(__imag__ x);
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
ret.val[0] = vdupq_n_f32(__real__ x);
ret.val[1] = vdupq_n_f32(__imag__ x);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -601,6 +740,13 @@ static inline simd_cf_t srslte_simd_cf_prod (simd_cf_t a, simd_cf_t b) {
_mm_mul_ps(a.im, b.im));
ret.im = _mm_add_ps(_mm_mul_ps(a.re, b.im),
_mm_mul_ps(a.im, b.re));
#else
#ifdef HAVE_NEON
ret.val[0] = vsubq_f32(vmulq_f32(a.val[0],b.val[0]),
vmulq_f32(a.val[1],b.val[1]));
ret.val[1] = vaddq_f32(vmulq_f32(a.val[0],b.val[1]),
vmulq_f32(a.val[1],b.val[0]));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -626,6 +772,13 @@ static inline simd_cf_t srslte_simd_cf_conjprod (simd_cf_t a, simd_cf_t b) {
_mm_mul_ps(a.im, b.im));
ret.im = _mm_sub_ps(_mm_mul_ps(a.im, b.re),
_mm_mul_ps(a.re, b.im));
#else
#ifdef HAVE_NEON
ret.val[0] = vaddq_f32(vmulq_f32(a.val[0],b.val[0]),
vmulq_f32(a.val[1],b.val[1]));
ret.val[1] = vsubq_f32(vmulq_f32(a.val[1],b.val[0]),
vmulq_f32(a.val[0],b.val[1]));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -645,6 +798,11 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) {
#ifdef LV_HAVE_SSE
ret.re = _mm_add_ps(a.re, b.re);
ret.im = _mm_add_ps(a.im, b.im);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
ret.val[0] = vaddq_f32(a.val[0],b.val[0]);
ret.val[1] = vaddq_f32(a.val[1],b.val[1]);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -665,6 +823,11 @@ static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) {
#ifdef LV_HAVE_SSE
ret.re = _mm_mul_ps(a.re, b);
ret.im = _mm_mul_ps(a.im, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
ret.val[0] = vmulq_f32(a.val[0],b);
ret.val[1] = vmulq_f32(a.val[1],b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -699,6 +862,16 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) {
simd_f_t neg_a_im = _mm_xor_ps(_mm_set1_ps(-0.0f), a.im);
ret.re = _mm_mul_ps(a.re, rcp);
ret.im = _mm_mul_ps(neg_a_im, rcp);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
simd_f_t a2re = vmulq_f32(a.val[0], a.val[0]);
simd_f_t a2im = vmulq_f32(a.val[1], a.val[1]);
simd_f_t mod2 = vaddq_f32(a2re, a2im);
simd_f_t rcp = vmulq_f32(vrecpeq_f32(mod2), vrecpsq_f32(vrecpeq_f32(mod2), mod2));
simd_f_t neg_a_im = vnegq_f32(a.val[1]);
ret.val[0] = vmulq_f32(a.val[0], rcp);
ret.val[1] = vmulq_f32(neg_a_im, rcp);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -718,7 +891,12 @@ static inline simd_cf_t srslte_simd_cf_zero (void) {
#ifdef LV_HAVE_SSE
ret.re = _mm_setzero_ps();
ret.im = _mm_setzero_ps();
#endif /* LV_HAVE_SSE */
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
ret.val[0] = vdupq_n_f32(0);
ret.val[1] = vdupq_n_f32(0);
#endif /* HAVE_NEON */
#endif /* HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
return ret;
@ -739,6 +917,11 @@ typedef __m256 simd_sel_t;
#ifdef LV_HAVE_SSE
typedef __m128i simd_i_t;
typedef __m128 simd_sel_t;
#else /* LV_HAVE_AVX2 */
#ifdef HAVE_NEON
typedef int32x4_t simd_i_t;
typedef int32x4_t simd_sel_t;
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -752,6 +935,10 @@ static inline simd_i_t srslte_simd_i_load(int *x) {
#else
#ifdef LV_HAVE_SSE
return _mm_load_si128((__m128i*)x);
#else
#ifdef HAVE_NEON
return vld1q_s32((int*)x);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -766,6 +953,10 @@ static inline void srslte_simd_i_store(int *x, simd_i_t reg) {
#else
#ifdef LV_HAVE_SSE
_mm_store_si128((__m128i*)x, reg);
#else
#ifdef HAVE_NEON
vst1q_s32((int*)x, reg);
#endif /*HAVE_NEON*/
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -780,6 +971,10 @@ static inline simd_i_t srslte_simd_i_set1(int x) {
#else
#ifdef LV_HAVE_SSE
return _mm_set1_epi32(x);
#else
#ifdef HAVE_NEON
return vdupq_n_s32(x);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -794,6 +989,10 @@ static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) {
#else
#ifdef LV_HAVE_SSE
return _mm_add_epi32(a, b);
#else
#ifdef HAVE_NEON
return vaddq_s32(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -808,6 +1007,10 @@ static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return (simd_sel_t) _mm_cmpgt_ps(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return (simd_sel_t) vcgtq_f32(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -822,6 +1025,23 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s
#else
#ifdef LV_HAVE_SSE
return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, selector);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON
int* a_ptr = (int*) &a;
int* b_ptr = (int*) &b;
simd_i_t ret;
int* sel = (int*) &selector;
int* c_ptr = (int*) &ret;
for(int i = 0;i<4;i++)
{
if(sel[i] == -1){
c_ptr[i] = b_ptr[i];
}else{
c_ptr[i] = a_ptr[i];
}
}
return ret;
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -841,6 +1061,10 @@ typedef __m256i simd_s_t;
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
typedef __m128i simd_s_t;
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
typedef int16x8_t simd_s_t;
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -854,6 +1078,10 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_load_si128((__m128i*) ptr);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vld1q_s16(ptr);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -868,6 +1096,10 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_loadu_si128((__m128i*) ptr);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vld1q_s16(ptr);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -882,6 +1114,10 @@ static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
_mm_store_si128((__m128i*) ptr, simdreg);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
vst1q_s16( ptr, simdreg);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -896,11 +1132,14 @@ static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
_mm_storeu_si128((__m128i*) ptr, simdreg);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
vst1q_s16(ptr, simdreg);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
}
static inline simd_s_t srslte_simd_s_zero(void) {
#ifdef LV_HAVE_AVX512
return _mm512_setzero_si512();
@ -910,6 +1149,10 @@ static inline simd_s_t srslte_simd_s_zero(void) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_setzero_si128();
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vdupq_n_s16(0);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -924,6 +1167,10 @@ static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_mullo_epi16(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vmulq_s16(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -938,6 +1185,10 @@ static inline simd_s_t srslte_simd_s_add(simd_s_t a, simd_s_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_add_epi16(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vaddq_s16(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -952,6 +1203,10 @@ static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) {
#else /* LV_HAVE_AVX2 */
#ifdef LV_HAVE_SSE
return _mm_sub_epi16(a, b);
#else /* LV_HAVE_SSE */
#ifdef HAVE_NEON
return vsubq_s16(a, b);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -962,8 +1217,9 @@ static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) {
#if SRSLTE_SIMD_C16_SIZE
typedef struct {
typedef
#ifdef LV_HAVE_AVX512
struct {
union {
__m512i m512;
int16_t i16[32];
@ -974,24 +1230,32 @@ typedef struct {
} im;
#else /* LV_HAVE_AVX512 */
#ifdef LV_HAVE_AVX2
union {
__m256i m256;
int16_t i16[16];
} re;
union {
__m256i m256;
int16_t i16[16];
} im;
struct {
union {
__m256i m256;
int16_t i16[16];
} re;
union {
__m256i m256;
int16_t i16[16];
} im;
#else
#ifdef LV_HAVE_SSE
union {
__m128i m128;
int16_t i16[8];
} re;
union {
__m128i m128;
int16_t i16[8];
} im;
struct {
union {
__m128i m128;
int16_t i16[8];
} re;
union {
__m128i m128;
int16_t i16[8];
} im;
#else
#ifdef HAVE_NEON
union {
int16x8x2_t m128;
int16_t i16[16];
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -1017,6 +1281,10 @@ static inline simd_c16_t srslte_simd_c16i_load(c16_t *ptr) {
__m128i in2 = _mm_load_si128((__m128i*)(ptr + 8));
ret.re.m128 = _mm_blend_epi16(in1,_mm_shufflelo_epi16(_mm_shufflehi_epi16(in2, 0b10100000), 0b10100000), 0b10101010);
ret.im.m128 = _mm_blend_epi16(_mm_shufflelo_epi16(_mm_shufflehi_epi16(in1, 0b11110101), 0b11110101),in2, 0b10101010);
#else /* LV_HAVE_SSE*/
#ifdef HAVE_NEON
ret.m128 = vld2q_s16((int16_t*)(ptr));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */
@ -1032,6 +1300,11 @@ static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) {
#ifdef LV_HAVE_SSE
ret.re.m128 = _mm_load_si128((__m128i*)(re));
ret.im.m128 = _mm_load_si128((__m128i*)(im));
#else /* LV_HAVE_SSE*/
#ifdef HAVE_NEON
ret.m128.val[0] = vld1q_s16((int16_t*)(re));
ret.m128.val[1] = vld1q_s16((int16_t*)(im));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
return ret;
@ -1046,6 +1319,11 @@ static inline simd_c16_t srslte_simd_c16_loadu(int16_t *re, int16_t *im) {
#ifdef LV_HAVE_SSE
ret.re.m128 = _mm_loadu_si128((__m128i*)(re));
ret.im.m128 = _mm_loadu_si128((__m128i*)(im));
#else /* LV_HAVE_SSE*/
#ifdef HAVE_NEON
ret.m128.val[0] = vld1q_s16((int16_t*)(re));
ret.m128.val[1] = vld1q_s16((int16_t*)(im));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
return ret;
@ -1063,6 +1341,10 @@ static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) {
__m128i im_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.im.m128, 0b10110001), 0b10110001);
_mm_store_si128((__m128i *) (ptr), _mm_blend_epi16(simdreg.re.m128, im_sw, 0b10101010));
_mm_store_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010));
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
vst2q_s16((int16_t*)(ptr) ,simdreg.m128);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
}
@ -1079,6 +1361,10 @@ static inline void srslte_simd_c16i_storeu(c16_t *ptr, simd_c16_t simdreg) {
__m128i im_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.im.m128, 0b10110001), 0b10110001);
_mm_storeu_si128((__m128i *) (ptr), _mm_blend_epi16(simdreg.re.m128, im_sw, 0b10101010));
_mm_storeu_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010));
#else /*HAVE_NEON*/
#ifdef HAVE_NEON
vst2q_s16((int16_t*)(ptr) ,simdreg.m128);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
}
@ -1091,6 +1377,11 @@ static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t si
#ifdef LV_HAVE_SSE
_mm_store_si128((__m128i *) re, simdreg.re.m128);
_mm_store_si128((__m128i *) im, simdreg.im.m128);
#else
#ifdef HAVE_NEON
vst1q_s16((int16_t *) re, simdreg.m128.val[0]);
vst1q_s16((int16_t *) im, simdreg.m128.val[1]);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
}
@ -1103,6 +1394,11 @@ static inline void srslte_simd_c16_storeu(int16_t *re, int16_t *im, simd_c16_t s
#ifdef LV_HAVE_SSE
_mm_storeu_si128((__m128i *) re, simdreg.re.m128);
_mm_storeu_si128((__m128i *) im, simdreg.im.m128);
#else
#ifdef HAVE_NEON
vst1q_s16((int16_t *) re, simdreg.m128.val[0]);
vst1q_s16((int16_t *) im, simdreg.m128.val[1]);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
}
@ -1134,6 +1430,11 @@ static inline simd_c16_t srslte_simd_c16_add (simd_c16_t a, simd_c16_t b) {
#ifdef LV_HAVE_SSE
ret.re.m128 = _mm_add_epi16(a.re.m128, b.re.m128);
ret.im.m128 = _mm_add_epi16(a.im.m128, b.im.m128);
#else
#ifdef HAVE_NEON
ret.m128.val[0] = vaddq_s16(a.m128.val[0],a.m128.val[0]);
ret.m128.val[1] = vaddq_s16(a.m128.val[1],a.m128.val[1]);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
return ret;
@ -1148,7 +1449,12 @@ static inline simd_c16_t srslte_simd_c16_zero (void) {
#ifdef LV_HAVE_SSE
ret.re.m128 = _mm_setzero_si128();
ret.im.m128 = _mm_setzero_si128();
#endif /* LV_HAVE_SSE */
#else
#ifdef HAVE_NEON
ret.m128.val[0] = vdupq_n_s16(0);
ret.m128.val[1] = vdupq_n_s16(0);
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
return ret;
}
@ -1182,6 +1488,12 @@ static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) {
__m128i ai = _mm_cvttps_epi32(a);
__m128i bi = _mm_cvttps_epi32(b);
return _mm_packs_epi32(ai, bi);
#else
#ifdef HAVE_NEON
int32x4_t ai = vcvtq_s32_f32(a);
int32x4_t bi = vcvtq_s32_f32(b);
return (simd_s_t)vcombine_s16(vqmovn_s32(ai), vqmovn_s32(bi));
#endif /* HAVE_NEON */
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX2 */
#endif /* LV_HAVE_AVX512 */

View File

@ -163,6 +163,8 @@ private:
static const int reordering_timeout_id = 1;
static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested
// Timer checks
bool status_prohibited();
bool poll_retx();

View File

@ -4764,6 +4764,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRU
if(plmn_id != NULL &&
ie_ptr != NULL)
{
if(0xFFFF == plmn_id->mcc) {
mcc_opt = false;
}
liblte_value_2_bits(mcc_opt, ie_ptr, 1);
if(true == mcc_opt)
@ -12754,7 +12757,241 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg,
Document Reference: 36.331 v10.0.0 Section 6.2.2
*********************************************************************/
// FIXME
LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info,
uint8 **ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(cgi_info != NULL &&
ie_ptr != NULL)
{
liblte_value_2_bits(cgi_info->have_plmn_identity_list, ie_ptr, 1);
liblte_rrc_pack_cell_global_id_eutra_ie(&cgi_info->cell_global_id, ie_ptr);
liblte_rrc_pack_tracking_area_code_ie(cgi_info->tracking_area_code, ie_ptr);
if(cgi_info->have_plmn_identity_list) {
liblte_value_2_bits(cgi_info->n_plmn_identity_list-1, ie_ptr, 3);
for(uint32 i=0; i<cgi_info->n_plmn_identity_list; i++) {
liblte_rrc_pack_plmn_identity_ie(&cgi_info->plmn_identity_list[i], ie_ptr);
}
}
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr,
LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(ie_ptr != NULL &&
cgi_info != NULL)
{
cgi_info->have_plmn_identity_list = (bool)liblte_bits_2_value(ie_ptr, 1);
liblte_rrc_unpack_cell_global_id_eutra_ie(ie_ptr, &cgi_info->cell_global_id);
liblte_rrc_unpack_tracking_area_code_ie(ie_ptr, &cgi_info->tracking_area_code);
if(cgi_info->have_plmn_identity_list) {
cgi_info->n_plmn_identity_list = liblte_bits_2_value(ie_ptr, 3) + 1;
for(uint32 i=0; i<cgi_info->n_plmn_identity_list; i++) {
liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cgi_info->plmn_identity_list[i]);
}
}
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result,
uint8 **ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(meas_result != NULL &&
ie_ptr != NULL)
{
//ext
liblte_value_2_bits(0, ie_ptr, 1);
//options
liblte_value_2_bits(meas_result->have_rsrp, ie_ptr, 1);
liblte_value_2_bits(meas_result->have_rsrq, ie_ptr, 1);
if(meas_result->have_rsrp) {
liblte_rrc_pack_rsrp_range_ie(meas_result->rsrp_result, ie_ptr);
}
if(meas_result->have_rsrq) {
liblte_rrc_pack_rsrq_range_ie(meas_result->rsrq_result, ie_ptr);
}
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(ie_ptr != NULL &&
meas_result != NULL)
{
//ext
bool ext = liblte_bits_2_value(ie_ptr, 1);
//options
meas_result->have_rsrp = liblte_bits_2_value(ie_ptr, 1);
meas_result->have_rsrq = liblte_bits_2_value(ie_ptr, 1);
if(meas_result->have_rsrp) {
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &meas_result->rsrp_result);
}
if(meas_result->have_rsrq) {
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &meas_result->rsrq_result);
}
//skip extensions
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra,
uint8 **ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(meas_result_eutra != NULL &&
ie_ptr != NULL)
{
liblte_value_2_bits(meas_result_eutra->have_cgi_info, ie_ptr, 1);
liblte_rrc_pack_phys_cell_id_ie(meas_result_eutra->phys_cell_id, ie_ptr);
if(meas_result_eutra->have_cgi_info) {
liblte_rrc_pack_cgi_info_ie(&meas_result_eutra->cgi_info, ie_ptr);
}
liblte_rrc_pack_meas_result_ie(&meas_result_eutra->meas_result, ie_ptr);
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(ie_ptr != NULL &&
meas_result_eutra != NULL)
{
meas_result_eutra->have_cgi_info = liblte_bits_2_value(ie_ptr, 1);
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_result_eutra->phys_cell_id);
if(meas_result_eutra->have_cgi_info) {
liblte_rrc_unpack_cgi_info_ie(ie_ptr, &meas_result_eutra->cgi_info);
}
liblte_rrc_unpack_meas_result_ie(ie_ptr, &meas_result_eutra->meas_result);
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report,
LIBLTE_BIT_MSG_STRUCT *msg)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 *msg_ptr = msg->msg;
if(meas_report != NULL &&
msg != NULL)
{
//MeasurementReport
liblte_value_2_bits(0, &msg_ptr, 1); //critical extensions
liblte_value_2_bits(0, &msg_ptr, 3); //c1
//MeasurementReport-r8-IEs
liblte_value_2_bits(0, &msg_ptr, 1); //non-critical extensions
//MeasResults
liblte_value_2_bits(0, &msg_ptr, 1); //ext
liblte_value_2_bits(meas_report->have_meas_result_neigh_cells, &msg_ptr, 1);
liblte_rrc_pack_meas_id_ie(meas_report->meas_id, &msg_ptr);
liblte_rrc_pack_rsrp_range_ie(meas_report->pcell_rsrp_result, &msg_ptr);
liblte_rrc_pack_rsrq_range_ie(meas_report->pcell_rsrq_result, &msg_ptr);
if(meas_report->have_meas_result_neigh_cells) {
liblte_value_2_bits(0, &msg_ptr, 1); //choice from before extension marker
liblte_value_2_bits(meas_report->meas_result_neigh_cells_choice, &msg_ptr, 2);
if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) {
printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]);
} else {
//MeasResultListEUTRA
liblte_value_2_bits(meas_report->meas_result_neigh_cells.eutra.n_result-1, &msg_ptr, 3);
for(uint32 i=0; i<meas_report->meas_result_neigh_cells.eutra.n_result; i++) {
liblte_rrc_pack_meas_result_eutra_ie(&meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i], &msg_ptr);
}
}
}
// Fill in the number of bits used
msg->N_bits = msg_ptr - msg->msg;
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT *msg,
LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 *msg_ptr = msg->msg;
if(msg != NULL &&
meas_report != NULL)
{
//MeasurementReport
bool crit_ext = liblte_bits_2_value(&msg_ptr, 1); //critical extensions
liblte_bits_2_value(&msg_ptr, 3); //c1
//MeasurementReport-r8-IEs
bool non_crit_ext = liblte_bits_2_value(&msg_ptr, 1); //non-critical extensions
//MeasResults
bool ext = liblte_bits_2_value(&msg_ptr, 1);
meas_report->have_meas_result_neigh_cells = liblte_bits_2_value(&msg_ptr, 1);
liblte_rrc_unpack_meas_id_ie(&msg_ptr, &meas_report->meas_id);
liblte_rrc_unpack_rsrp_range_ie(&msg_ptr, &meas_report->pcell_rsrp_result);
liblte_rrc_unpack_rsrq_range_ie(&msg_ptr, &meas_report->pcell_rsrq_result);
if(meas_report->have_meas_result_neigh_cells) {
liblte_bits_2_value(&msg_ptr, 1); //choice from before extension marker
meas_report->meas_result_neigh_cells_choice = (LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM) liblte_bits_2_value(&msg_ptr, 2);
if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) {
printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]);
} else {
//MeasResultListEUTRA
meas_report->meas_result_neigh_cells.eutra.n_result = liblte_bits_2_value(&msg_ptr, 3) + 1;
for(uint32 i=0; i<meas_report->meas_result_neigh_cells.eutra.n_result; i++) {
liblte_rrc_unpack_meas_result_eutra_ie(&msg_ptr, &meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i]);
}
}
}
//skip extensions
liblte_rrc_consume_noncrit_extension(crit_ext, __func__, &msg_ptr);
liblte_rrc_consume_noncrit_extension(non_crit_ext, __func__, &msg_ptr);
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
err = LIBLTE_SUCCESS;
}
return(err);
}
/*********************************************************************
Message Name: MBSFN Area Configuration
@ -13550,9 +13787,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_
err = liblte_rrc_pack_csfb_parameters_request_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg,
&global_msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){
printf("NOT HANDLING MEASUREMENT REPORT\n");
// err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg,
// &global_msg);
err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg,
&global_msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){
err = liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
&global_msg);
@ -13630,9 +13866,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m
err = liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(&global_msg,
(LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){
printf("NOT HANDLING MEASUREMENT REPORT\n");
// err = liblte_rrc_unpack_measurement_report_msg(&global_msg,
// (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg);
err = liblte_rrc_unpack_measurement_report_msg(&global_msg,
(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){
err = liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(&global_msg,
(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg);

View File

@ -823,7 +823,7 @@ void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
// Section 6.2.3
void rar_subh::write_payload(uint8_t** ptr)
{
*(*ptr + 0) = (uint8_t) (ta&0x7f0)>>4;
*(*ptr + 0) = (uint8_t) ((ta&0x7f0)>>4);
*(*ptr + 1) = (uint8_t) ((ta&0xf) <<4) | (grant[0]<<3) | (grant[1]<<2) | (grant[2]<<1) | grant[3];
uint8_t *x = &grant[4];
*(*ptr + 2) = (uint8_t) srslte_bit_pack(&x, 8);

View File

@ -605,7 +605,7 @@ int srslte_band_get_fd_region(enum band_geographical_area region, srslte_earfcn_
/* Returns the interval tti1-tti2 mod 10240 */
uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) {
if (tti1 > tti2) {
if (tti1 >= tti2) {
return tti1-tti2;
} else {
return 10240-tti2+tti1;

View File

@ -56,9 +56,7 @@ void srslte_dft_load() {
void srslte_dft_exit() {
#ifdef FFTW_WISDOM_FILE
if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) {
fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE);
}
fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE);
#endif
}
@ -93,6 +91,27 @@ static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len
plan->out = fftwf_malloc(size_out*len);
}
int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points, cf_t *in_buffer,
cf_t *out_buffer, int istride, int ostride, int how_many,
int idist, int odist) {
int sign = (plan->forward) ? FFTW_FORWARD : FFTW_BACKWARD;
const fftwf_iodim iodim = {new_dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist};
/* Destroy current plan */
fftwf_destroy_plan(plan->p);
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = new_dft_points;
plan->init_size = plan->size;
return 0;
}
int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
if (plan->p) {
@ -107,6 +126,32 @@ int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
return 0;
}
int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir, cf_t *in_buffer,
cf_t *out_buffer, int istride, int ostride, int how_many,
int idist, int odist) {
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
const fftwf_iodim iodim = {dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist};
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_DFT_COMPLEX;
plan->dir = dir;
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;
plan->mirror = false;
plan->db = false;
plan->norm = false;
plan->dc = false;
plan->is_guru = true;
return 0;
}
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
@ -123,6 +168,7 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
plan->db = false;
plan->norm = false;
plan->dc = false;
plan->is_guru = false;
return 0;
}
@ -232,6 +278,14 @@ void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) {
plan->forward, plan->mirror, plan->dc);
}
void srslte_dft_run_guru_c(srslte_dft_plan_t *plan) {
if (plan->is_guru == true) {
fftwf_execute(plan->p);
} else {
fprintf(stderr, "srslte_dft_run_guru_c: the selected plan is not guru!\n");
}
}
void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) {
float norm;
int i;
@ -255,8 +309,10 @@ void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) {
void srslte_dft_plan_free(srslte_dft_plan_t *plan) {
if (!plan) return;
if (!plan->size) return;
if (plan->in) fftwf_free(plan->in);
if (plan->out) fftwf_free(plan->out);
if (!plan->is_guru) {
if (plan->in) fftwf_free(plan->in);
if (plan->out) fftwf_free(plan->out);
}
if (plan->p) fftwf_destroy_plan(plan->p);
bzero(plan, sizeof(srslte_dft_plan_t));
}

View File

@ -37,23 +37,79 @@
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
/* Uncomment next line for avoiding Guru DFT call */
//#define AVOID_GURU
int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) {
return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM);
int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) {
return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM);
}
int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) {
int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) {
/* Set OFDM object attributes */
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT);
q->cp = cp;
q->freq_shift = false;
q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz);
q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz);
q->in_buffer = in_buffer;
q->out_buffer= out_buffer;
if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) {
fprintf(stderr, "Error: Creating DFT plan\n");
return -1;
}
#ifdef AVOID_GURU
q->tmp = srslte_vec_malloc((uint32_t) symbol_sz * sizeof(cf_t));
if (!q->tmp) {
perror("malloc");
return -1;
}
bzero(q->tmp, sizeof(cf_t) * symbol_sz);
#else
int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz);
if (!q->tmp) {
perror("malloc");
return -1;
}
bzero(q->tmp, sizeof(cf_t) * q->sf_sz);
if (dir == SRSLTE_DFT_BACKWARD) {
bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp));
}else {
bzero(in_buffer, sizeof(cf_t) * q->sf_sz);
}
for (int slot = 0; slot < 2; slot++) {
//bzero(&q->fft_plan_sf[slot], sizeof(srslte_dft_plan_t));
//bzero(q->tmp + SRSLTE_CP_NSYMB(cp)*symbol_sz*slot, sizeof(cf_t) * (cp1 + (SRSLTE_CP_NSYMB(cp) - 1)*cp2 + SRSLTE_CP_NSYMB(cp)*symbol_sz));
if (dir == SRSLTE_DFT_FORWARD) {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
in_buffer + cp1 + q->slot_sz * slot,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
} else {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
out_buffer + cp1 + q->slot_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
}
}
#endif
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz));
if (!q->shift_buffer) {
@ -64,15 +120,6 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int
srslte_dft_plan_set_mirror(&q->fft_plan, true);
srslte_dft_plan_set_dc(&q->fft_plan, true);
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT);
q->cp = cp;
q->freq_shift = false;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols,
q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);
@ -101,9 +148,60 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz);
q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz);
#ifndef AVOID_GURU
cf_t *in_buffer = q->in_buffer;
cf_t *out_buffer = q->out_buffer;
int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
srslte_dft_dir_t dir = q->fft_plan_sf[0].dir;
if (q->tmp) {
free(q->tmp);
}
q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz);
if (!q->tmp) {
perror("malloc");
return -1;
}
bzero(q->tmp, sizeof(cf_t) * q->sf_sz);
if (dir == SRSLTE_DFT_BACKWARD) {
bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp));
}else {
bzero(in_buffer, sizeof(cf_t) * q->sf_sz);
}
for (int slot = 0; slot < 2; slot++) {
srslte_dft_plan_free(&q->fft_plan_sf[slot]);
if (dir == SRSLTE_DFT_FORWARD) {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
in_buffer + cp1 + q->slot_sz * slot,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
} else {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
out_buffer + cp1 + q->slot_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
}
}
#endif /* AVOID_GURU */
if (q->freq_shift) {
srslte_ofdm_set_freq_shift(q, q->freq_shift_f);
@ -118,6 +216,15 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof
void srslte_ofdm_free_(srslte_ofdm_t *q) {
srslte_dft_plan_free(&q->fft_plan);
#ifndef AVOID_GURU
for (int slot = 0; slot < 2; slot++) {
if (q->fft_plan_sf[slot].init_size) {
srslte_dft_plan_free(&q->fft_plan_sf[slot]);
}
}
#endif
if (q->tmp) {
free(q->tmp);
}
@ -127,28 +234,28 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
bzero(q, sizeof(srslte_ofdm_t));
}
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) {
int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
return -1;
}
q->max_prb = max_prb;
return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD);
return srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_FORWARD);
}
int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb)
int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb)
{
int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN);
return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN);
}
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) {
uint32_t i;
int ret;
@ -158,7 +265,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
return -1;
}
q->max_prb = max_prb;
ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD);
ret = srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD);
if (ret == SRSLTE_SUCCESS) {
@ -173,7 +280,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
return ret;
}
int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb)
int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb)
{
uint32_t i;
int ret;
@ -184,7 +291,7 @@ int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb
return -1;
}
ret = srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN);
ret = srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN);
if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, false);
@ -207,7 +314,8 @@ int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
}
return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
} else {
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n");
fprintf(stderr, "OFDM (Rx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb, q->max_prb);
return -1;
}
}
@ -234,7 +342,8 @@ int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
}
return ret;
} else {
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n");
fprintf(stderr, "OFDM (Tx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb, q->max_prb);
return -1;
}
}
@ -274,8 +383,12 @@ void srslte_ofdm_tx_free(srslte_ofdm_t *q) {
/* Transforms input samples into output OFDM symbols.
* Performs FFT on a each symbol and removes CP.
*/
void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
void srslte_ofdm_rx_slot(srslte_ofdm_t *q, int slot_in_sf) {
cf_t *output = q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols;
#ifdef AVOID_GURU
uint32_t i;
cf_t *input = q->in_buffer + slot_in_sf * q->slot_sz;
for (i=0;i<q->nof_symbols;i++) {
input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
srslte_dft_run_c(&q->fft_plan, input, q->tmp);
@ -283,6 +396,25 @@ void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
input += q->symbol_sz;
output += q->nof_re;
}
#else
float norm = 1.0f/sqrtf(q->fft_plan.size);
cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols;
uint32_t dc = (q->fft_plan.dc) ? 1:0;
srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]);
for (int i = 0; i < q->nof_symbols; i++) {
memcpy(output, tmp + q->symbol_sz - q->nof_re / 2, sizeof(cf_t) * q->nof_re / 2);
memcpy(output + q->nof_re / 2, &tmp[dc], sizeof(cf_t) * q->nof_re / 2);
if (q->fft_plan.norm) {
srslte_vec_sc_prod_cfc(output, norm, output, q->nof_re);
}
tmp += q->symbol_sz;
output += q->nof_re;
}
#endif
}
void srslte_ofdm_rx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
@ -314,29 +446,32 @@ void srslte_ofdm_rx_slot_zerocopy(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
}
}
void srslte_ofdm_rx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
uint32_t n;
void srslte_ofdm_rx_sf(srslte_ofdm_t *q) {
uint32_t n;
if (q->freq_shift) {
srslte_vec_prod_ccc(input, q->shift_buffer, input, 2*q->slot_sz);
srslte_vec_prod_ccc(q->in_buffer, q->shift_buffer, q->in_buffer, 2*q->slot_sz);
}
if(!q->mbsfn_subframe){
for (n=0;n<2;n++) {
srslte_ofdm_rx_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]);
srslte_ofdm_rx_slot(q, n);
}
}
else{
srslte_ofdm_rx_slot_mbsfn(q, &input[0*q->slot_sz], &output[0*q->nof_re*q->nof_symbols]);
srslte_ofdm_rx_slot(q, &input[1*q->slot_sz], &output[1*q->nof_re*q->nof_symbols]);
srslte_ofdm_rx_slot_mbsfn(q, &q->in_buffer[0*q->slot_sz], &q->out_buffer[0*q->nof_re*q->nof_symbols]);
srslte_ofdm_rx_slot(q, 1);
}
}
/* Transforms input OFDM symbols into output samples.
* Performs FFT on a each symbol and adds CP.
*/
void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
uint32_t i, cp_len;
for (i=0;i<q->nof_symbols;i++) {
cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
void srslte_ofdm_tx_slot(srslte_ofdm_t *q, int slot_in_sf) {
cf_t *input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols;
cf_t *output = q->out_buffer + slot_in_sf * q->slot_sz;
#ifdef AVOID_GURU
for (int i=0;i<q->nof_symbols;i++) {
int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]);
input += q->nof_re;
@ -344,6 +479,60 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t));
output += q->symbol_sz + cp_len;
}
#else
float norm = 1.0f/sqrtf(q->symbol_sz);
cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols;
bzero(tmp, q->slot_sz);
uint32_t dc = (q->fft_plan.dc) ? 1:0;
for (int i = 0; i < q->nof_symbols; i++) {
memcpy(&tmp[dc], &input[q->nof_re / 2], q->nof_re / 2 * sizeof(cf_t));
memcpy(&tmp[q->symbol_sz - q->nof_re / 2], &input[0], q->nof_re / 2 * sizeof(cf_t));
input += q->nof_re;
tmp += q->symbol_sz;
}
srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]);
for (int i=0;i<q->nof_symbols;i++) {
int cp_len = SRSLTE_CP_ISNORM(q->cp) ? SRSLTE_CP_LEN_NORM(i, q->symbol_sz) : SRSLTE_CP_LEN_EXT(q->symbol_sz);
if (q->fft_plan.norm) {
srslte_vec_sc_prod_cfc(&output[cp_len], norm, &output[cp_len], q->symbol_sz);
}
/* add CP */
memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t));
output += q->symbol_sz + cp_len;
}
#endif
/*input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols;
cf_t *output2 = srslte_vec_malloc(sizeof(cf_t) * q->slot_sz);
cf_t *o2 = output2;
bzero(q->tmp, sizeof(cf_t)*q->symbol_sz);
//bzero(output2, sizeof(cf_t)*q->slot_sz);
for (int i=0;i<q->nof_symbols;i++) {
int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
srslte_dft_run_c(&q->fft_plan, q->tmp, &o2[cp_len]);
input += q->nof_re;
memcpy(o2, &o2[q->symbol_sz], cp_len * sizeof(cf_t));
o2 += q->symbol_sz + cp_len;
}
cf_t *output1 = q->out_buffer + slot_in_sf * q->slot_sz;//srslte_vec_malloc(sizeof(cf_t) * q->slot_sz);
for (int i = 0; i < q->slot_sz; i++) {
float error = cabsf(output1[i] - output2[i])/cabsf(output2[i]);
cf_t k = output1[i]/output2[i];
if (error > 0.1) printf("%d/%05d error=%f output=%+f%+fi gold=%+f%+fi k=%+f%+fi\n", slot_in_sf, i, error,
__real__ output1[i], __imag__ output1[i],
__real__ output2[i], __imag__ output2[i],
__real__ k, __imag__ k);
}
free(output2);/**/
}
void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
@ -369,20 +558,20 @@ void srslte_ofdm_set_normalize(srslte_ofdm_t *q, bool normalize_enable) {
srslte_dft_plan_set_norm(&q->fft_plan, normalize_enable);
}
void srslte_ofdm_tx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output)
void srslte_ofdm_tx_sf(srslte_ofdm_t *q)
{
uint32_t n;
uint32_t n;
if(!q->mbsfn_subframe){
for (n=0;n<2;n++) {
srslte_ofdm_tx_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]);
srslte_ofdm_tx_slot(q, n);
}
}
else{
srslte_ofdm_tx_slot_mbsfn(q, &input[0*q->nof_re*q->nof_symbols], &output[0*q->slot_sz]);
srslte_ofdm_tx_slot(q, &input[1*q->nof_re*q->nof_symbols], &output[1*q->slot_sz]);
srslte_ofdm_tx_slot_mbsfn(q, &q->in_buffer[0*q->nof_re*q->nof_symbols], &q->out_buffer[0*q->slot_sz]);
srslte_ofdm_tx_slot(q, 1);
}
if (q->freq_shift) {
srslte_vec_prod_ccc(output, q->shift_buffer, output, 2*q->slot_sz);
srslte_vec_prod_ccc(q->out_buffer, q->shift_buffer, q->out_buffer, 2*q->slot_sz);
}
}

View File

@ -35,16 +35,28 @@
int nof_prb = -1;
srslte_cp_t cp = SRSLTE_CP_NORM;
int nof_repetitions = 128;
static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) {
if (ts_end->tv_usec > ts_start->tv_usec) {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 +
(double) ts_end->tv_usec - (double) ts_start->tv_usec;
} else {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec - 1) * 1000000 +
((double) ts_end->tv_usec + 1000000) - (double) ts_start->tv_usec;
}
}
void usage(char *prog) {
printf("Usage: %s\n", prog);
printf("\t-n nof_prb [Default All]\n");
printf("\t-e extended cyclic prefix [Default Normal]\n");
printf("\t-r nof_repetitions [Default %d]\n", nof_repetitions);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "ne")) != -1) {
while ((opt = getopt(argc, argv, "ner")) != -1) {
switch (opt) {
case 'n':
nof_prb = atoi(argv[optind]);
@ -52,6 +64,9 @@ void parse_args(int argc, char **argv) {
case 'e':
cp = SRSLTE_CP_EXT;
break;
case 'r':
nof_repetitions = atoi(argv[optind]);
break;
default:
usage(argv[0]);
exit(-1);
@ -61,6 +76,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
struct timeval start, end;
srslte_ofdm_t fft, ifft;
cf_t *input, *outfft, *outifft;
float mse;
@ -81,48 +97,65 @@ int main(int argc, char **argv) {
printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout);
input = malloc(sizeof(cf_t) * n_re);
input = srslte_vec_malloc(sizeof(cf_t) * n_re * 2);
if (!input) {
perror("malloc");
exit(-1);
}
outfft = malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)));
outfft = srslte_vec_malloc(sizeof(cf_t) * n_re * 2);
if (!outfft) {
perror("malloc");
exit(-1);
}
outifft = malloc(sizeof(cf_t) * n_re);
outifft = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2);
if (!outifft) {
perror("malloc");
exit(-1);
}
bzero(outifft, sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2);
if (srslte_ofdm_rx_init(&fft, cp, n_prb)) {
if (srslte_ofdm_rx_init(&fft, cp, outifft, outfft, n_prb)) {
fprintf(stderr, "Error initializing FFT\n");
exit(-1);
}
srslte_dft_plan_set_norm(&fft.fft_plan, true);
srslte_ofdm_set_normalize(&fft, true);
if (srslte_ofdm_tx_init(&ifft, cp, n_prb)) {
if (srslte_ofdm_tx_init(&ifft, cp, input, outifft, n_prb)) {
fprintf(stderr, "Error initializing iFFT\n");
exit(-1);
}
srslte_dft_plan_set_norm(&ifft.fft_plan, true);
srslte_ofdm_set_normalize(&ifft, true);
for (i=0;i<n_re;i++) {
input[i] = 100 * ((float) rand()/RAND_MAX + (float) I*rand()/RAND_MAX);
input[i] = 100 * ((float) rand() / (float) RAND_MAX + I * ((float) rand() / (float) RAND_MAX));
//input[i] = 100;
}
srslte_ofdm_tx_slot(&ifft, input, outfft);
srslte_ofdm_rx_slot(&fft, outfft, outifft);
gettimeofday(&start, NULL);
for (int i = 0; i < nof_repetitions; i++) {
srslte_ofdm_tx_slot(&ifft, 0);
}
gettimeofday(&end, NULL);\
printf(" Tx@%.1fMsps", (float)(SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))*nof_repetitions)/elapsed_us(&start, &end));
gettimeofday(&start, NULL);
for (int i = 0; i < nof_repetitions; i++) {
srslte_ofdm_rx_slot(&fft, 0);
}
gettimeofday(&end, NULL);\
printf(" Rx@%.1fMsps", (float)(SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))*nof_repetitions)/elapsed_us(&start, &end));
/* compute MSE */
mse = 0;
mse = 0.0f;
for (i=0;i<n_re;i++) {
mse += cabsf(input[i] - outifft[i]);
cf_t error = input[i] - outfft[i];
mse += (__real__ error * __real__ error + __imag__ error * __imag__ error)/cabsf(input[i]);
if (mse > 1.0f) printf("%04d. %+.1f%+.1fi Vs. %+.1f%+.1f %+.1f%+.1f (mse=%f)\n", i, __real__ input[i], __imag__ input[i], __real__ outifft[i], __imag__ outifft[i], __real__ outfft[i], __imag__ outfft[i], mse);
}
printf("MSE=%f\n", mse);
/*for (i=0;i<n_re;i++) {
mse += cabsf(input[i] - outfft[i]);
}*/
printf(" MSE=%.6f\n", mse);
if (mse >= 0.07) {
printf("MSE too large\n");

View File

@ -31,6 +31,7 @@
#include <string.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#include <srslte/phy/dft/ofdm.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -41,7 +42,7 @@
#define SRSLTE_ENB_RF_AMP 0.1
int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -53,13 +54,22 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
q->cfi = 3;
q->tx_amp = SRSLTE_ENB_RF_AMP;
if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->sf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols[i]) {
perror("malloc");
goto clean_exit;
}
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
}
srslte_ofdm_set_normalize(&q->ifft, true);
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (srslte_ofdm_tx_init(&q->ifft[i], SRSLTE_CP_NORM, q->sf_symbols[i], out_buffer[i], max_prb)) {
fprintf(stderr, "Error initiating FFT (%d)\n", i);
goto clean_exit;
}
}
if (srslte_pbch_init(&q->pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
@ -89,15 +99,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
goto clean_exit;
}
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->sf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols[i]) {
perror("malloc");
goto clean_exit;
}
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
}
ret = SRSLTE_SUCCESS;
} else {
@ -114,7 +115,9 @@ clean_exit:
void srslte_enb_dl_free(srslte_enb_dl_t *q)
{
if (q) {
srslte_ofdm_tx_free(&q->ifft);
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
srslte_ofdm_tx_free(&q->ifft[i]);
}
srslte_regs_free(&q->regs);
srslte_pbch_free(&q->pbch);
srslte_pcfich_free(&q->pcfich);
@ -152,9 +155,11 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR;
}
if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return SRSLTE_ERROR;
for (int i = 0; i < q->cell.nof_ports; i++) {
if (srslte_ofdm_tx_set_prb(&q->ifft[i], q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error re-planning iFFT (%d)\n", i);
return SRSLTE_ERROR;
}
}
if (srslte_pbch_set_cell(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n");
@ -264,14 +269,15 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti)
}
void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer)
void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q)
{
srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[0], signal_buffer);
// TODO: PAPR control
float norm_factor = (float) sqrt(q->cell.nof_prb)/15;
srslte_vec_sc_prod_cfc(signal_buffer, q->tx_amp*norm_factor, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft[0].symbol_sz);
for (int i = 0; i < q->cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&q->ifft[i]);
srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, q->tx_amp*norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
}
}
int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti)

View File

@ -40,6 +40,7 @@
#define MAX_CANDIDATES 16
int srslte_enb_ul_init(srslte_enb_ul_t *q,
cf_t *in_buffer,
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -55,8 +56,20 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q,
perror("malloc");
goto clean_exit;
}
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
goto clean_exit;
}
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer, q->sf_symbols, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
@ -80,18 +93,6 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q,
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
goto clean_exit;
}
ret = SRSLTE_SUCCESS;
} else {
@ -254,7 +255,7 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer)
{
srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols);
srslte_ofdm_rx_sf(&q->fft);
}
int get_pucch(srslte_enb_ul_t *q, uint16_t rnti,

View File

@ -1454,7 +1454,7 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_
return srslte_predecoding_single_multi(y, h[0], x[0], nof_rxant, nof_symbols, noise_estimate);
} else {
fprintf(stderr,
"Number of ports and layers must be 1 for transmission on single antenna ports\n");
"Number of ports and layers must be 1 for transmission on single antenna ports (%d, %d)\n", nof_ports, nof_layers);
return -1;
}
break;

View File

@ -44,6 +44,7 @@ int srslte_demod_hard_demodulate(srslte_demod_hard_t* q, cf_t* symbols, uint8_t
int nbits=-1;
switch(q->mod) {
case SRSLTE_MOD_LAST:
case SRSLTE_MOD_BPSK:
hard_bpsk_demod(symbols,bits,nsymbols);
nbits=nsymbols;

View File

@ -82,6 +82,7 @@ int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, uint32_t nsymbo
int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation) {
srslte_modem_table_init(q);
switch(modulation) {
case SRSLTE_MOD_LAST:
case SRSLTE_MOD_BPSK:
q->nbits_x_symbol = 1;
q->nsymbols = 2;

View File

@ -32,6 +32,7 @@
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/phy/phch/ra.h>
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/common/phy_common.h"
@ -111,7 +112,7 @@ int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, uint32_t nof_prb,
srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start,
nof_prb, nof_prb);
if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, 0)) {
if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) {
return SRSLTE_ERROR;
}
@ -177,7 +178,7 @@ int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, uint32_t nof_prb,
return ret;
}
if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, harq_pid)) {
if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) {
return ret;
}
@ -1159,7 +1160,32 @@ int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
} else if (msg->format == SRSLTE_DCI_FORMAT2A) {
data->pinfo = srslte_bit_pack(&y, precoding_bits_f2a(nof_ports));
}
// Table 5.3.3.1.5-1
if (SRSLTE_RA_DL_GRANT_NOF_TB(data) == 2) {
if (data->tb_cw_swap) {
uint32_t tmp = data->rv_idx;
data->rv_idx = data->rv_idx_1;
data->rv_idx_1 = tmp;
tmp = data->mcs_idx;
data->mcs_idx = data->mcs_idx_1;
data->mcs_idx_1 = tmp;
bool tmp_ndi = data->ndi;
data->ndi = data->ndi_1;
data->ndi_1 = tmp_ndi;
}
}
// Table 5.3.3.1.5-2
if (!data->tb_en[0]) {
data->rv_idx = data->rv_idx_1;
data->mcs_idx = data->mcs_idx_1;
data->ndi = data->ndi_1;
data->tb_en[1] = false;
}
return SRSLTE_SUCCESS;
}

View File

@ -477,6 +477,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
cfg->sf_idx = sf_idx;
memcpy(cfg->rv, rvidx, sizeof(uint32_t) * SRSLTE_MAX_CODEWORDS);
cfg->mimo_type = mimo_type;
cfg->tb_cw_swap = grant->tb_cw_swap;
/* Check and configure PDSCH transmission modes */
switch(mimo_type) {
@ -492,7 +493,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb);
return SRSLTE_ERROR;
}
cfg->nof_layers = 2;
cfg->nof_layers = cell.nof_ports;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
if (nof_tb == 1) {
@ -543,19 +544,19 @@ static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti,
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx) {
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
uint32_t rv = cfg->rv[codeword_idx];
uint32_t codeword_idx, uint32_t tb_idx) {
srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx];
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx];
uint32_t rv = cfg->rv[tb_idx];
if (nbits->nof_bits) {
INFO("Encoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
INFO("Encoding PDSCH SF: %d (TB%d -> CW%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, tb_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
nbits->nof_re, nbits->nof_bits, rv);
/* Channel coding */
if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) {
ERROR("Error encoding TB %d", codeword_idx);
if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], tb_idx)) {
ERROR("Error encoding (TB%d -> CW%d)", tb_idx, codeword_idx);
return SRSLTE_ERROR;
}
@ -577,15 +578,15 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx, bool *ack) {
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
uint32_t rv = cfg->rv[codeword_idx];
uint32_t codeword_idx, uint32_t tb_idx, bool *ack) {
srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx];
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx];
uint32_t rv = cfg->rv[tb_idx];
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (softbuffer && data && ack) {
INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
INFO("Decoding PDSCH SF: %d (CW%d -> TB%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, codeword_idx, tb_idx, srslte_mod_string(mcs->mod), mcs->tbs,
nbits->nof_re, nbits->nof_bits, rv);
/* demodulate symbols
@ -601,7 +602,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c
srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits);
/* Return */
ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, codeword_idx);
ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx);
q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch);
@ -610,6 +611,9 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c
} else if (ret == SRSLTE_ERROR) {
*ack = false;
ret = SRSLTE_SUCCESS;
} else if (ret == SRSLTE_ERROR_INVALID_INPUTS) {
*ack = false;
ret = SRSLTE_ERROR;
}
} else {
ERROR("Detected NULL pointer in TB%d &softbuffer=%p &data=%p &ack=%p", codeword_idx, softbuffer, (void*)data, ack);
@ -677,24 +681,32 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
}
// Pre-decoder
srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
if (srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate)<0) {
return -1;
}
// Layer demapping only if necessary
if (cfg->nof_layers != nof_tb) {
srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb,
nof_symbols[0], nof_symbols, cfg->mimo_type);
}
// Codeword decoding
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
/* Decode only if transport block is enabled and the default ACK is not true */
if (cfg->grant.tb_en[tb] && !acks[tb]) {
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]);
/* Check if there has been any execution error */
if (ret) {
return ret;
/* Codeword decoding: Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */
uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0;
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
/* Decode only if transport block is enabled and the default ACK is not true */
if (cfg->grant.tb_en[tb_idx]) {
if (!acks[tb_idx]) {
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]);
/* Check if there has been any execution error */
if (ret) {
return ret;
}
}
cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS;
}
}
@ -767,20 +779,23 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
}
/* If both transport block size is zero return error */
if (cfg->grant.mcs[0].tbs == 0) {
if (!nof_tb) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (cfg->nbits[0].nof_re > q->max_re) {
if (cfg->nbits[0].nof_re > q->max_re || cfg->nbits[1].nof_re > q->max_re) {
fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb);
return SRSLTE_ERROR_INVALID_INPUTS;
}
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
if (cfg->grant.tb_en[tb]) {
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
/* Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */
uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0;
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
if (cfg->grant.tb_en[tb_idx]) {
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx);
cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS;
}
}

View File

@ -185,108 +185,87 @@ int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_
}
}
srslte_mod_t last_mod[8];
uint32_t last_ul_tbs_idx[8];
uint32_t last_dl_tbs[8];
uint32_t last_dl_tbs2[8];
static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t harq_pid) {
int tbs = -1;
static void ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) {
// 8.6.2 First paragraph
if (dci->mcs_idx <= 28) {
/* Table 8.6.1-1 on 36.213 */
if (dci->mcs_idx < 11) {
grant->mcs.mod = SRSLTE_MOD_QPSK;
tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb);
last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb);
} else if (dci->mcs_idx < 21) {
grant->mcs.mod = SRSLTE_MOD_16QAM;
tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb);
last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-1;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb);
} else if (dci->mcs_idx < 29) {
grant->mcs.mod = SRSLTE_MOD_64QAM;
tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb);
last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-2;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb);
} else {
fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx);
}
last_mod[harq_pid%8] = grant->mcs.mod;
} else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) {
// 8.6.1 and 8.6.2 36.213 second paragraph
grant->mcs.mod = SRSLTE_MOD_QPSK;
tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb);
dci->rv_idx = 1;
grant->mcs.tbs = 0;
dci->rv_idx = 1;
} else if (dci->mcs_idx >= 29) {
// Else use last TBS/Modulation and use mcs to obtain rv_idx
tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb);
grant->mcs.mod = last_mod[harq_pid%8];
// Else use last TBS/Modulation and use mcs to obtain rv_idx
grant->mcs.tbs = -1;
grant->mcs.mod = SRSLTE_MOD_LAST;
dci->rv_idx = dci->mcs_idx - 28;
DEBUG("TTI=%d, harq_pid=%d, mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n",
harq_pid, harq_pid%8, dci->mcs_idx, tbs/8, grant->mcs.mod, dci->rv_idx);
}
if (tbs < 0) {
fprintf(stderr, "Error computing TBS\n");
return SRSLTE_ERROR;
} else {
grant->mcs.tbs = (uint32_t) tbs;
return SRSLTE_SUCCESS;
DEBUG("mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n",
dci->mcs_idx, grant->mcs.tbs/8, grant->mcs.mod, dci->rv_idx);
}
}
void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, uint32_t N_srs, srslte_ra_nbits_t *nbits)
void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, uint32_t N_srs, srslte_ra_nbits_t *nbits)
{
nbits->nof_symb = 2*(SRSLTE_CP_NSYMB(cp)-1) - N_srs;
nbits->nof_symb = 2*(SRSLTE_CP_NSYMB(cp)-1) - N_srs;
nbits->nof_re = nbits->nof_symb*grant->M_sc;
nbits->nof_bits = nbits->nof_re * grant->Qm;
}
/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */
int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant,
uint32_t harq_pid)
int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant)
{
// Compute PRB allocation
// Compute PRB allocation
if (!srslte_ra_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) {
// Compute MCS
if (!ul_dci_to_grant_mcs(dci, grant, harq_pid)) {
// Fill rest of grant structure
grant->mcs.idx = dci->mcs_idx;
grant->M_sc = grant->L_prb*SRSLTE_NRE;
grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be?
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
} else {
fprintf(stderr, "Error computing MCS\n");
return SRSLTE_ERROR;
}
// Compute MCS
ul_dci_to_grant_mcs(dci, grant);
// Fill rest of grant structure
grant->mcs.idx = dci->mcs_idx;
grant->M_sc = grant->L_prb*SRSLTE_NRE;
grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be?
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
} else {
printf("Error computing UL PRB allocation\n");
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols)
uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols)
{
uint32_t nof_refs = 0;
uint32_t nof_refs = 0;
uint32_t nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nof_ctrl_symbols;
switch(cell.nof_ports) {
case 1:
nof_refs = 2*3;
break;
case 2:
nof_refs = 4*3;
break;
case 4:
nof_refs = 4*4;
break;
case 1:
nof_refs = 2*3;
break;
case 2:
nof_refs = 4*3;
break;
case 4:
nof_refs = 4*4;
break;
}
return nof_prb * (nof_symb*SRSLTE_NRE-nof_refs);
}
/* Computes the number of RE for each PRB in the prb_dist structure */
uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell,
uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell,
uint32_t sf_idx, uint32_t nof_ctrl_symbols)
{
uint32_t j, s;
@ -300,7 +279,7 @@ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t ce
}
}
}
return nof_re;
return nof_re;
}
@ -315,7 +294,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
uint32_t bitmask;
uint32_t P = srslte_ra_type0_P(nof_prb);
uint32_t n_rb_rbg_subset, n_rb_type1;
bzero(grant, sizeof(srslte_ra_dl_grant_t));
switch (dci->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
@ -352,14 +331,14 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
* P * P + dci->type1_alloc.rbg_subset * P + (i + shift) % P] = true;
grant->nof_prb++;
} else {
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
}
}
memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool));
break;
case SRSLTE_RA_ALLOC_TYPE2:
if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
for (i = 0; i < dci->type2_alloc.L_crb; i++) {
grant->prb_idx[0][i + dci->type2_alloc.RB_start] = true;
grant->nof_prb++;
@ -408,13 +387,13 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
if (n_tilde_prb_odd < nof_prb) {
grant->prb_idx[0][n_tilde_prb_odd] = true;
} else {
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
} else {
if (n_tilde_prb_odd + N_gap - N_tilde_vrb / 2 < nof_prb) {
grant->prb_idx[0][n_tilde_prb_odd + N_gap - N_tilde_vrb / 2] = true;
} else {
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
}
grant->nof_prb++;
@ -422,13 +401,13 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
if(n_tilde_prb_even < nof_prb) {
grant->prb_idx[1][n_tilde_prb_even] = true;
} else {
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
} else {
if (n_tilde_prb_even + N_gap - N_tilde_vrb / 2 < nof_prb) {
grant->prb_idx[1][n_tilde_prb_even + N_gap - N_tilde_vrb / 2] = true;
} else {
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
}
}
@ -442,8 +421,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
}
int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
uint32_t i_tbs = 0;
int tbs = -1;
int i_tbs = 0;
if (mcs->idx < 10) {
mcs->mod = SRSLTE_MOD_QPSK;
i_tbs = mcs->idx;
@ -455,30 +433,26 @@ int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
i_tbs = mcs->idx-2;
} else if (mcs->idx == 29) {
mcs->mod = SRSLTE_MOD_QPSK;
tbs = 0;
i_tbs = 0;
i_tbs = -1;
} else if (mcs->idx == 30) {
mcs->mod = SRSLTE_MOD_16QAM;
tbs = 0;
i_tbs = 0;
i_tbs = -1;
} else if (mcs->idx == 31) {
mcs->mod = SRSLTE_MOD_64QAM;
tbs = 0;
i_tbs = 0;
i_tbs = -1;
}
if (tbs == -1) {
int tbs = -1;
if (i_tbs >= 0) {
tbs = srslte_ra_tbs_from_idx(i_tbs, nprb);
if (tbs >= 0) {
mcs->tbs = tbs;
}
}
return tbs;
mcs->tbs = tbs;
}
return tbs;
}
int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) {
uint32_t i_tbs = 0;
int tbs = -1;
uint32_t i_tbs = 0;
int tbs = -1;
if (mcs->idx < 5) {
mcs->mod = SRSLTE_MOD_QPSK;
i_tbs = mcs->idx*2;
@ -492,7 +466,7 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) {
mcs->mod = SRSLTE_MOD_64QAM;
i_tbs = mcs->idx + 5;
}else if (mcs->idx < 28) {
//mcs->mod = SRSLTE_MOD_256QAM;
//mcs->mod = SRSLTE_MOD_256QAM;
i_tbs = mcs->idx + 5;
}else if (mcs->idx == 28) {
mcs->mod = SRSLTE_MOD_QPSK;
@ -511,15 +485,15 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) {
tbs = 0;
i_tbs = 0;
}
if (tbs == -1) {
tbs = srslte_ra_tbs_from_idx(i_tbs, nprb);
if (tbs >= 0) {
mcs->tbs = tbs;
mcs->tbs = tbs;
}
}
return tbs;
}
return tbs;
}
/* Modulation order and transport block size determination 7.1.7 in 36.213
@ -530,9 +504,9 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) {
* */
static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) {
uint32_t n_prb=0;
int tbs = -1;
uint32_t i_tbs = 0;
int tbs = -1;
uint32_t i_tbs = 0;
if (!crc_is_crnti) {
if (dci->dci_is_1a) {
n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3;
@ -546,35 +520,21 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
}
} else {
fprintf(stderr, "Error decoding DCI: P/SI/RA-RNTI supports Format1A/1C only\n");
return SRSLTE_ERROR;
return SRSLTE_ERROR;
}
grant->mcs[0].mod = SRSLTE_MOD_QPSK;
grant->mcs[0].tbs = (uint32_t) tbs;
} else {
n_prb = grant->nof_prb;
grant->nof_tb = 0;
if (dci->tb_en[0]) {
grant->mcs[0].idx = dci->mcs_idx;
tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb);
if (tbs) {
last_dl_tbs[dci->harq_process%8] = tbs;
} else {
// For mcs>=29, set last TBS received for this PID
grant->mcs[0].tbs = last_dl_tbs[dci->harq_process%8];
}
grant->nof_tb++;
grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb);
} else {
grant->mcs[0].tbs = 0;
}
if (dci->tb_en[1]) {
grant->mcs[1].idx = dci->mcs_idx_1;
tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb);
if (tbs) {
last_dl_tbs2[dci->harq_process%8] = tbs;
} else {
// For mcs>=29, set last TBS received for this PID
grant->mcs[1].tbs = last_dl_tbs2[dci->harq_process%8];
}
grant->mcs[1].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb);
} else {
grant->mcs[1].tbs = 0;
}
@ -586,8 +546,9 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
}
}
grant->pinfo = dci->pinfo;
grant->tb_cw_swap = dci->tb_cw_swap;
if (tbs < 0) {
if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) {
return SRSLTE_ERROR;
} else {
return SRSLTE_SUCCESS;
@ -599,10 +560,10 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
{
// Compute number of RE
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
if (grant->tb_en[i]) {
/* Compute number of RE for first transport block */
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
if (SRSLTE_SF_NORM == grant->sf_type) {
nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart;
} else if (SRSLTE_SF_MBSFN == grant->sf_type) {
@ -622,10 +583,12 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
crc_is_crnti = true;
}
// Compute PRB allocation
if (!srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb)) {
// Compute MCS
if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) {
// Compute PRB allocation
int ret =srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb);
if (!ret) {
// Compute MCS
ret = dl_dci_to_grant_mcs(dci, grant, crc_is_crnti);
if (ret == SRSLTE_SUCCESS) {
// Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0
if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END &&
dci->dci_is_1c)
@ -907,4 +870,4 @@ void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
}
}
}
}

View File

@ -458,12 +458,12 @@ static int decode_tb(srslte_sch_t *q,
if (cb_segm->F) {
fprintf(stderr, "Error filler bits are not supported. Use standard TBS\n");
return SRSLTE_ERROR;
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (cb_segm->C > softbuffer->max_cb) {
fprintf(stderr, "Error number of CB (%d) exceeds soft buffer size (%d CBs)\n", cb_segm->C, softbuffer->max_cb);
return SRSLTE_ERROR;
return SRSLTE_ERROR_INVALID_INPUTS;
}
bool crc_ok = true;
@ -517,15 +517,15 @@ int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf
int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
int16_t *e_bits, uint8_t *data, int codeword_idx) {
int16_t *e_bits, uint8_t *data, int tb_idx) {
uint32_t Nl = 1;
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
Nl = 2;
}
return decode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx],
cfg->grant.Qm[codeword_idx] * Nl, cfg->rv[codeword_idx], cfg->nbits[codeword_idx].nof_bits,
return decode_tb(q, softbuffer, &cfg->cb_segm[tb_idx],
cfg->grant.Qm[tb_idx] * Nl, cfg->rv[tb_idx], cfg->nbits[tb_idx].nof_bits,
e_bits, data);
}
@ -546,15 +546,15 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf
}
int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, uint8_t *e_bits, int codeword_idx) {
uint8_t *data, uint8_t *e_bits, int tb_idx) {
uint32_t Nl = 1;
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
Nl = 2;
}
return encode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], cfg->grant.Qm[codeword_idx]*Nl, cfg->rv[codeword_idx],
cfg->nbits[codeword_idx].nof_bits, data, e_bits);
return encode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], cfg->grant.Qm[tb_idx]*Nl, cfg->rv[tb_idx],
cfg->nbits[tb_idx].nof_bits, data, e_bits);
}
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits

View File

@ -119,6 +119,14 @@ add_test(pdsch_test_multiplex1cw_p0_50 pdsch_test -x multiplex -a 2 -p 0 -n 50)
add_test(pdsch_test_multiplex1cw_p0_75 pdsch_test -x multiplex -a 2 -p 0 -n 75)
add_test(pdsch_test_multiplex1cw_p0_100 pdsch_test -x multiplex -a 2 -p 0 -n 100)
# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword, swapped)
add_test(pdsch_test_multiplex1cw_p0_6_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 6 -F 1)
add_test(pdsch_test_multiplex1cw_p0_15_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 15)
add_test(pdsch_test_multiplex1cw_p0_25_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 25)
add_test(pdsch_test_multiplex1cw_p0_50_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 50)
add_test(pdsch_test_multiplex1cw_p0_75_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 75)
add_test(pdsch_test_multiplex1cw_p0_100_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 100)
# PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (1 codeword)
add_test(pdsch_test_multiplex1cw_p1_6 pdsch_test -x multiplex -a 2 -p 1 -n 6)
add_test(pdsch_test_multiplex1cw_p1_12 pdsch_test -x multiplex -a 2 -p 1 -n 12)
@ -151,6 +159,14 @@ add_test(pdsch_test_multiplex2cw_p0_50 pdsch_test -x multiplex -a 2 -t 0 -p 0 -
add_test(pdsch_test_multiplex2cw_p0_75 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 75)
add_test(pdsch_test_multiplex2cw_p0_100 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 100)
# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (2 codeword, swapped)
add_test(pdsch_test_multiplex2cw_p0_6_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 6 -w -F 1)
add_test(pdsch_test_multiplex2cw_p0_12_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 12 -w)
add_test(pdsch_test_multiplex2cw_p0_25_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 25 -w)
add_test(pdsch_test_multiplex2cw_p0_50_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 50 -w)
add_test(pdsch_test_multiplex2cw_p0_75_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 75 -w)
add_test(pdsch_test_multiplex2cw_p0_100_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 100 -w)
# PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (2 codeword)
add_test(pdsch_test_multiplex2cw_p1_6 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 6)
add_test(pdsch_test_multiplex2cw_p1_12 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 12)

View File

@ -140,7 +140,7 @@ int base_init() {
return -1;
}
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n");
return -1;
}
@ -203,7 +203,7 @@ int main(int argc, char **argv) {
if (nread > 0) {
// process 1st subframe only
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer);
srslte_ofdm_rx_sf(&fft);
/* Get channel estimates for each port */
srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0);

View File

@ -120,15 +120,15 @@ int base_init() {
fmatlab = NULL;
}
flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb));
flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb));
input_buffer = malloc(flen * sizeof(cf_t));
input_buffer = srslte_vec_malloc(flen * sizeof(cf_t));
if (!input_buffer) {
perror("malloc");
exit(-1);
}
fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
fft_buffer = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!fft_buffer) {
perror("malloc");
return -1;
@ -151,7 +151,7 @@ int base_init() {
return -1;
}
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n");
return -1;
}
@ -215,7 +215,7 @@ int main(int argc, char **argv) {
n = srslte_filesource_read(&fsrc, input_buffer, flen);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer);
srslte_ofdm_rx_sf(&fft);
if (fmatlab) {
fprintf(fmatlab, "infft=");

View File

@ -126,7 +126,7 @@ int base_init() {
exit(-1);
}
flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb)));
flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz_power2(cell.nof_prb)));
input_buffer = malloc(flen * sizeof(cf_t));
if (!input_buffer) {
@ -157,7 +157,7 @@ int base_init() {
return -1;
}
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n");
return -1;
}
@ -231,7 +231,7 @@ int main(int argc, char **argv) {
INFO("Reading %d samples sub-frame %d\n", flen, frame_cnt);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer);
srslte_ofdm_rx_sf(&fft);
/* Get channel estimates for each port */
srslte_chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10);

View File

@ -129,7 +129,7 @@ int base_init() {
exit(-1);
}
flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb)));
flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb));
input_buffer[0] = malloc(flen * sizeof(cf_t));
if (!input_buffer[0]) {
@ -137,7 +137,7 @@ int base_init() {
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}

View File

@ -59,6 +59,7 @@ uint32_t subframe = 1;
int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1};
uint16_t rnti = 1234;
uint32_t nof_rx_antennas = 1;
bool tb_cw_swap = false;
uint32_t pmi = 0;
char *input_file = NULL;
@ -77,12 +78,13 @@ void usage(char *prog) {
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-a nof_rx_antennas [Default %d]\n", nof_rx_antennas);
printf("\t-p pmi (multiplex only) [Default %d]\n", pmi);
printf("\t-w Swap Transport Blocks\n");
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "fmMcsrtRFpnavx")) != -1) {
while ((opt = getopt(argc, argv, "fmMcsrtRFpnawvx")) != -1) {
switch(opt) {
case 'f':
input_file = argv[optind];
@ -123,6 +125,9 @@ void parse_args(int argc, char **argv) {
case 'a':
nof_rx_antennas = (uint32_t) atoi(argv[optind]);
break;
case 'w':
tb_cw_swap = true;
break;
case 'v':
srslte_verbose++;
break;
@ -207,6 +212,11 @@ int main(int argc, char **argv) {
dci.tb_en[1] = true;
}
/* Enable swap */
if (SRSLTE_RA_DL_GRANT_NOF_TB(&dci) == SRSLTE_MAX_TB && tb_cw_swap) {
dci.tb_cw_swap = tb_cw_swap;
}
/* Generate grant from DCI */
if (srslte_ra_dl_dci_to_grant(&dci, cell.nof_prb, rnti, &grant)) {
fprintf(stderr, "Error computing resource allocation\n");
@ -255,7 +265,7 @@ int main(int argc, char **argv) {
}
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
for (i = 0; i < SRSLTE_MAX_TB; i++) {
if (grant.tb_en[i]) {
data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs);
if (!data_tx[i]) {
@ -271,6 +281,9 @@ int main(int argc, char **argv) {
}
bzero(data_rx[i], sizeof(uint8_t) * grant.mcs[i].tbs);
} else {
data_tx[i] = NULL;
data_rx[i] = NULL;
}
}

View File

@ -144,7 +144,7 @@ int base_init() {
fmatlab = NULL;
}
flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb));
flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb));
input_buffer = malloc(flen * sizeof(cf_t));
if (!input_buffer) {
@ -175,7 +175,7 @@ int base_init() {
return -1;
}
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n");
return -1;
}
@ -242,7 +242,7 @@ int main(int argc, char **argv) {
n = srslte_filesource_read(&fsrc, input_buffer, flen);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer);
srslte_ofdm_rx_sf(&fft);
if (fmatlab) {
fprintf(fmatlab, "infft=");

View File

@ -140,7 +140,7 @@ int base_init() {
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}

View File

@ -139,7 +139,7 @@ cf_t *tx_slot_symbols[SRSLTE_MAX_PORTS];
cf_t *rx_slot_symbols[SRSLTE_MAX_PORTS];
srslte_pmch_t pmch_tx, pmch_rx;
srslte_pdsch_cfg_t pmch_cfg;
srslte_ofdm_t ifft_mbsfn, fft_mbsfn;
srslte_ofdm_t ifft_mbsfn[SRSLTE_MAX_PORTS], fft_mbsfn[SRSLTE_MAX_PORTS];
int main(int argc, char **argv) {
uint32_t i, j, k;
@ -167,12 +167,11 @@ int main(int argc, char **argv) {
/* If transport block 0 is enabled */
grant.tb_en[0] = true;
grant.tb_en[1] = false;
grant.nof_tb = 1;
grant.mcs[0].idx = mcs_idx;
grant.nof_prb = cell.nof_prb;
grant.sf_type = SRSLTE_SF_MBSFN;
srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb);
grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod);
for(int i = 0; i < 2; i++){
@ -181,41 +180,6 @@ int main(int argc, char **argv) {
}
}
#ifdef DO_OFDM
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, non_mbsfn_region);
srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn, non_mbsfn_region);
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
srslte_ofdm_set_normalize(&fft_mbsfn, true);
for (i = 0; i < cell.nof_ports; i++) {
tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
for (i = 0; i < nof_rx_antennas; i++) {
rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
#endif /* DO_OFDM */
/* Configure PDSCH */
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) {
fprintf(stderr, "Error configuring PMCH\n");
exit(-1);
}
/* init memory */
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
for (j = 0; j < SRSLTE_MAX_PORTS; j++) {
@ -235,6 +199,25 @@ int main(int argc, char **argv) {
}
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers_tx[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers_tx[i]) {
fprintf(stderr, "Error allocating TX soft buffer\n");
}
if (srslte_softbuffer_tx_init(softbuffers_tx[i], cell.nof_prb)) {
fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit;
}
}
for (i = 0; i < cell.nof_ports; i++) {
tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t));
if (!tx_slot_symbols[i]) {
perror("srslte_vec_malloc");
goto quit;
}
}
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant.tb_en[i]) {
@ -256,7 +239,7 @@ int main(int argc, char **argv) {
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers_rx[i] = calloc(sizeof(srslte_softbuffer_rx_t), 1);
if (!softbuffers_rx[i]) {
@ -269,6 +252,44 @@ int main(int argc, char **argv) {
goto quit;
}
}
#ifdef DO_OFDM
for (i = 0; i < cell.nof_ports; i++) {
tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn[i], SRSLTE_CP_EXT, tx_slot_symbols[i], tx_sf_symbols[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn[i], non_mbsfn_region);
srslte_ofdm_set_normalize(&ifft_mbsfn[i], true);
}
for (i = 0; i < nof_rx_antennas; i++) {
rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn[i], SRSLTE_CP_EXT, rx_sf_symbols[i], rx_slot_symbols[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn[i], non_mbsfn_region);
srslte_ofdm_set_normalize(&fft_mbsfn[i], true);
}
#endif /* DO_OFDM */
/* Configure PDSCH */
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) {
fprintf(stderr, "Error configuring PMCH\n");
exit(-1);
}
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) {
fprintf(stderr, "Error configuring PMCH\n");
@ -312,25 +333,7 @@ int main(int argc, char **argv) {
srslte_pmch_set_area_id(&pmch_rx, mbsfn_area_id);
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers_tx[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers_tx[i]) {
fprintf(stderr, "Error allocating TX soft buffer\n");
}
if (srslte_softbuffer_tx_init(softbuffers_tx[i], cell.nof_prb)) {
fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit;
}
}
for (i = 0; i < cell.nof_ports; i++) {
tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t));
if (!tx_slot_symbols[i]) {
perror("srslte_vec_malloc");
goto quit;
}
}
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (grant.tb_en[tb]) {
@ -353,7 +356,7 @@ int main(int argc, char **argv) {
#ifdef DO_OFDM
for (i = 0; i < cell.nof_ports; i++) {
/* For each Tx antenna modulate OFDM */
srslte_ofdm_tx_sf(&ifft_mbsfn, tx_slot_symbols[i], tx_sf_symbols[i]);
srslte_ofdm_tx_sf(&ifft_mbsfn[i]);
}
@ -387,7 +390,7 @@ int main(int argc, char **argv) {
#ifdef DO_OFDM
/* For each Rx antenna demodulate OFDM */
for (i = 0; i < nof_rx_antennas; i++) {
srslte_ofdm_rx_sf(&fft_mbsfn, tx_sf_symbols[i], rx_slot_symbols[i]);
srslte_ofdm_rx_sf(&fft_mbsfn[i]);
}
#endif
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {

View File

@ -136,7 +136,7 @@ int main(int argc, char **argv) {
dci.mcs_idx = mcs_idx;
srslte_ra_ul_grant_t grant;
if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant, 0)) {
if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant)) {
fprintf(stderr, "Error computing resource allocation\n");
return ret;
}

View File

@ -286,11 +286,6 @@ double rf_soapy_set_rx_srate(void *h, double rate)
return SRSLTE_ERROR;
}
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_RX, 0, rate) != 0) {
printf("setBandwidth Rx failed: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR;
}
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0);
}
@ -302,11 +297,6 @@ double rf_soapy_set_tx_srate(void *h, double rate)
return SRSLTE_ERROR;
}
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, 0, rate) != 0) {
printf("setBandwidth Tx failed: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR;
}
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0);
}

View File

@ -108,8 +108,8 @@ int main(int argc, char **argv) {
perror("malloc");
exit(-1);
}
if (srslte_ofdm_tx_init(&ifft, cp, nof_prb)) {
if (srslte_ofdm_tx_init(&ifft, cp, buffer, fft_buffer, nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
@ -150,8 +150,14 @@ int main(int argc, char **argv) {
/* Transform to OFDM symbols */
memset(fft_buffer, 0, sizeof(cf_t) * FLEN);
srslte_ofdm_tx_sf(&ifft, buffer, &fft_buffer[offset]);
srslte_ofdm_tx_sf(&ifft);
/* Apply sample offset */
for (int i = 0; i < FLEN; i++) {
fft_buffer[FLEN - i - 1 + offset] = fft_buffer[FLEN - i - 1];
}
bzero(fft_buffer, sizeof(cf_t) * offset);
if (srslte_sync_find(&syncobj, fft_buffer, 0, &find_idx) < 0) {
fprintf(stderr, "Error running srslte_sync_find\n");
exit(-1);

View File

@ -53,6 +53,7 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO
const uint32_t nof_common_formats = 2;
int srslte_ue_dl_init(srslte_ue_dl_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb,
uint32_t nof_rx_antennas)
{
@ -73,12 +74,35 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
q->sample_offset = 0;
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols_m[j]) {
perror("malloc");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) {
perror("malloc");
goto clean_exit;
}
bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t));
}
}
if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, max_prb)) {
q->sf_symbols = q->sf_symbols_m[0];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = q->ce_m[i][0];
}
for (int i = 0; i < nof_rx_antennas; i++) {
if (srslte_ofdm_rx_init(&q->fft[i], SRSLTE_CP_NORM, in_buffer[i], q->sf_symbols_m[i], max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
}
if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, in_buffer[0], q->sf_symbols_m[0], max_prb)) {
fprintf(stderr, "Error initiating FFT for MBSFN subframes \n");
goto clean_exit;
}
@ -127,28 +151,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error initiating SFO correct\n");
goto clean_exit;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft.symbol_sz);
for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols_m[j]) {
perror("malloc");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) {
perror("malloc");
goto clean_exit;
}
bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t));
}
}
q->sf_symbols = q->sf_symbols_m[0];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = q->ce_m[i][0];
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz);
ret = SRSLTE_SUCCESS;
} else {
@ -164,7 +167,9 @@ clean_exit:
void srslte_ue_dl_free(srslte_ue_dl_t *q) {
if (q) {
srslte_ofdm_rx_free(&q->fft);
for (int port = 0; port < SRSLTE_MAX_PORTS; port++) {
srslte_ofdm_rx_free(&q->fft[port]);
}
srslte_ofdm_rx_free(&q->fft_mbsfn);
srslte_chest_dl_free(&q->chest);
srslte_regs_free(&q->regs);
@ -219,10 +224,12 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
fprintf(stderr, "Error resizing SFO correct\n");
return SRSLTE_ERROR;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz);
for (int port = 0; port < q->nof_rx_antennas; port++) {
if (srslte_ofdm_rx_set_prb(&q->fft[port], q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
}
if (srslte_chest_dl_set_cell(&q->chest, q->cell)) {
fprintf(stderr, "Error resizing channel estimator\n");
@ -339,9 +346,9 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE
/* Run FFT for all subframe data */
for (int j=0;j<q->nof_rx_antennas;j++) {
if(sf_type == SRSLTE_SF_MBSFN ) {
srslte_ofdm_rx_sf(&q->fft_mbsfn, input[j], q->sf_symbols_m[j]);
srslte_ofdm_rx_sf(&q->fft_mbsfn);
}else{
srslte_ofdm_rx_sf(&q->fft, input[j], q->sf_symbols_m[j]);
srslte_ofdm_rx_sf(&q->fft[j]);
}
/* Correct SFO multiplying by complex exponential in the time domain */
@ -351,7 +358,7 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE
srslte_cfo_correct(&q->sfo_correct,
&q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
&q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
q->sample_offset / q->fft.symbol_sz);
q->sample_offset / q->fft[j].symbol_sz);
}
}
}
@ -601,9 +608,9 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q,
//float noise_estimate = 0;
grant.sf_type = SRSLTE_SF_MBSFN;
grant.nof_tb = 1;
grant.mcs[0].idx = 2;
grant.tb_en[0] = true;
grant.tb_en[1] = false;
grant.nof_prb = q->pmch.cell.nof_prb;
srslte_dl_fill_ra_mcs(&grant.mcs[0], grant.nof_prb);
srslte_softbuffer_rx_reset_tbs(q->softbuffers[0], (uint32_t) grant.mcs[0].tbs);

View File

@ -35,7 +35,8 @@
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
int srslte_ue_mib_init(srslte_ue_mib_t * q,
int srslte_ue_mib_init(srslte_ue_mib_t * q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -65,7 +66,7 @@ int srslte_ue_mib_init(srslte_ue_mib_t * q,
}
}
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer[0], q->sf_symbols, max_prb)) {
fprintf(stderr, "Error initializing FFT\n");
goto clean_exit;
}
@ -143,14 +144,14 @@ void srslte_ue_mib_reset(srslte_ue_mib_t * q)
srslte_pbch_decode_reset(&q->pbch);
}
int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
int srslte_ue_mib_decode(srslte_ue_mib_t * q,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset)
{
int ret = SRSLTE_SUCCESS;
cf_t *ce_slot1[SRSLTE_MAX_PORTS];
/* Run FFT for the slot symbols */
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols);
srslte_ofdm_rx_sf(&q->fft);
/* Get channel estimates of sf idx #0 for each port */
ret = srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0);
@ -198,7 +199,7 @@ int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
}
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ue_mib_init(&q->ue_mib, SRSLTE_UE_MIB_NOF_PRB)) {
if (srslte_ue_mib_init(&q->ue_mib, q->sf_buffer, SRSLTE_UE_MIB_NOF_PRB)) {
fprintf(stderr, "Error initiating ue_mib\n");
return SRSLTE_ERROR;
}
@ -274,7 +275,7 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
return -1;
} else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) {
if (ret == 1) {
mib_ret = srslte_ue_mib_decode(&q->ue_mib, q->sf_buffer[0], bch_payload, nof_tx_ports, sfn_offset);
mib_ret = srslte_ue_mib_decode(&q->ue_mib, bch_payload, nof_tx_ports, sfn_offset);
} else {
DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt);
srslte_ue_mib_reset(&q->ue_mib);

View File

@ -359,6 +359,11 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) {
return q->peak_idx;
}
void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) {
srslte_sync_set_cfo_ema_alpha(&q->sfind, ema);
srslte_sync_set_cfo_ema_alpha(&q->strack, ema);
}
srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) {
return q->state;
}

View File

@ -41,6 +41,7 @@
#define DEFAULT_CFO_TOL 50.0 // Hz
int srslte_ue_ul_init(srslte_ue_ul_t *q,
cf_t *out_buffer,
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -50,8 +51,14 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_ul_t));
if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, q->sf_symbols, out_buffer, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
@ -83,11 +90,6 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->refsignal) {
perror("malloc");
@ -347,7 +349,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
q->last_pucch_format = format;
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
srslte_ofdm_tx_sf(&q->fft);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
@ -417,7 +419,7 @@ int srslte_ue_ul_srs_encode(srslte_ue_ul_t *q, uint32_t tti, cf_t *output_signal
}
}
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
srslte_ofdm_tx_sf(&q->fft);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
@ -486,7 +488,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
}
}
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
srslte_ofdm_tx_sf(&q->fft);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));

View File

@ -31,6 +31,12 @@
#include <string.h>
#include <stddef.h>
#ifdef LV_HAVE_SSE
#include <immintrin.h>
#endif /* LV_HAVE_SSE */
#include "srslte/phy/utils/bit.h"
void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, uint32_t nof_bits) {
@ -53,6 +59,125 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i
}
w_offset_p=8-w_offset;
}
#ifdef LV_HAVE_SSE
__m64 m64mask = _mm_setr_pi8((uint8_t) 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
__m128i m128mask = _mm_set1_epi64(m64mask);
union {
uint8_t v[8];
__m64 m64;
} a, b, c;
union {
__m128i m128;
uint16_t u16[8];
uint8_t u8[16];
struct {
__m64 reg_a;
__m64 reg_b;
} m64;
struct {
uint16_t i0, i1, i2, i3, i4, i5, i6, i7;
} v;
} ipx, epx, ipx2, epx2, b128, a128, c128;
uint32_t i = st;
for (; i < (nof_bits / 8 - 1); i += 2) {
ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8) - w_offset_p));
epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E));
ipx2.m128 = _mm_loadu_si128((__m128i *) (interleaver + ((i + 1) * 8) - w_offset_p));
epx2.m128 = _mm_shuffle_epi8(ipx2.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E));
epx.m64.reg_b = epx2.m64.reg_a;
b128.m128 = _mm_and_si128(epx.m128, _mm_set1_epi8(0x7));
b128.m128 = _mm_shuffle_epi8(m128mask, b128.m128);
ipx.m128 = _mm_srli_epi16(ipx.m128, 3);
ipx2.m128 = _mm_srli_epi16(ipx2.m128, 3);
a128.m128 = _mm_set_epi8(input[ipx2.v.i0],
input[ipx2.v.i1],
input[ipx2.v.i2],
input[ipx2.v.i3],
input[ipx2.v.i4],
input[ipx2.v.i5],
input[ipx2.v.i6],
input[ipx2.v.i7],
input[ipx.v.i0],
input[ipx.v.i1],
input[ipx.v.i2],
input[ipx.v.i3],
input[ipx.v.i4],
input[ipx.v.i5],
input[ipx.v.i6],
input[ipx.v.i7]);
c128.m128 = _mm_cmpeq_epi8(_mm_and_si128(a128.m128, b128.m128), b128.m128);
uint16_t o = (uint16_t) _mm_movemask_epi8(c128.m128);
*((uint16_t *) (output + i)) = o;
}
for (; i < nof_bits / 8; i++) {
ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + i * 8 - w_offset_p));
epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E));
b.m64 = _mm_and_si64(epx.m64.reg_a, _mm_set1_pi8(0x7));
b.m64 = _mm_shuffle_pi8(m64mask, b.m64);
ipx.m128 = _mm_srli_epi16(ipx.m128, 3);
a.m64 = _mm_set_pi8(input[ipx.v.i0],
input[ipx.v.i1],
input[ipx.v.i2],
input[ipx.v.i3],
input[ipx.v.i4],
input[ipx.v.i5],
input[ipx.v.i6],
input[ipx.v.i7]);
c.m64 = _mm_cmpeq_pi8(_mm_and_si64(a.m64, b.m64), b.m64);
output[i] = (uint8_t) _mm_movemask_pi8(c.m64);
}
#if 0
/* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */
uint8_t *output2 = malloc(nof_bits/8);
for (i=st;i<nof_bits/8;i++) {
uint16_t i_p0 = interleaver[i*8+0-w_offset_p];
uint16_t i_p1 = interleaver[i*8+1-w_offset_p];
uint16_t i_p2 = interleaver[i*8+2-w_offset_p];
uint16_t i_p3 = interleaver[i*8+3-w_offset_p];
uint16_t i_p4 = interleaver[i*8+4-w_offset_p];
uint16_t i_p5 = interleaver[i*8+5-w_offset_p];
uint16_t i_p6 = interleaver[i*8+6-w_offset_p];
uint16_t i_p7 = interleaver[i*8+7-w_offset_p];
uint8_t out0 = (input[i_p0/8] & mask[i_p0%8])?mask[0]:(uint8_t)0;
uint8_t out1 = (input[i_p1/8] & mask[i_p1%8])?mask[1]:(uint8_t)0;
uint8_t out2 = (input[i_p2/8] & mask[i_p2%8])?mask[2]:(uint8_t)0;
uint8_t out3 = (input[i_p3/8] & mask[i_p3%8])?mask[3]:(uint8_t)0;
uint8_t out4 = (input[i_p4/8] & mask[i_p4%8])?mask[4]:(uint8_t)0;
uint8_t out5 = (input[i_p5/8] & mask[i_p5%8])?mask[5]:(uint8_t)0;
uint8_t out6 = (input[i_p6/8] & mask[i_p6%8])?mask[6]:(uint8_t)0;
uint8_t out7 = (input[i_p7/8] & mask[i_p7%8])?mask[7]:(uint8_t)0;
output2[i] = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7;
}
for(i = st; i < nof_bits/8; i++) {
if (output[i] != output2[i]) {
printf("%05d/%05d %02X %02X\n", i, nof_bits/8, output[i], output2[i]);
}
//output[i] = output2[i];
}
free(output2);
#endif
#else /* LV_HAVE_SSE */
for (uint32_t i=st;i<nof_bits/8;i++) {
uint16_t i_p0 = interleaver[i*8+0-w_offset_p];
@ -75,6 +200,7 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i
output[i] = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7;
}
#endif /* LV_HAVE_SSE */
for (uint32_t j=0;j<nof_bits%8;j++) {
uint16_t i_p = interleaver[(nof_bits/8)*8+j-w_offset];
if (input[i_p/8] & mask[i_p%8]) {

View File

@ -63,12 +63,12 @@ bool verbose = false;
strncpy(func_name, #X, 32);\
CODE;\
passed = (mse < MAX_MSE);\
printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed\n", func_name, block_size, \
(double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not");\
printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed (%.6f)\n", func_name, block_size, \
(double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not", mse);\
return passed;\
}
#define MALLOC(TYPE, NAME) TYPE *NAME = malloc(sizeof(TYPE)*block_size)
#define MALLOC(TYPE, NAME) TYPE *NAME = srslte_vec_malloc(sizeof(TYPE)*block_size)
static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) {
@ -507,7 +507,7 @@ TEST(srslte_vec_abs_cf,
for (int i = 0; i < block_size; i++) {
gold = sqrtf(crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i]));
mse += cabsf(gold - z[i]);
mse += cabsf(gold - z[i])/block_size;
}
free(x);
@ -771,12 +771,27 @@ int main(int argc, char **argv) {
size_count++;
}
char fname[68];
FILE *f = NULL;
void * p = popen("(date +%g%m%d && hostname) | tr '\\r\\n' '__'", "r");
if (p) {
fgets(fname, 64, p);
strncpy(fname + strnlen(fname, 64) - 1, ".tsv", 4);
f = fopen(fname, "w");
if (f) printf("Saving benchmark results in '%s'\n", fname);
}
pclose(p);
printf("\n");
printf("%32s |", "Subroutine/MSps");
if (f) fprintf(f, "Subroutine/MSps Vs Vector size\t");
for (int i = 0; i < size_count; i++) {
printf(" %7d", sizes[i]);
if (f) fprintf(f, "%d\t", sizes[i]);
}
printf(" |\n");
if (f) fprintf(f, "\n");
for (int j = 0; j < 32; j++) {
printf("-");
@ -789,12 +804,19 @@ int main(int argc, char **argv) {
for (int i = 0; i < func_count; i++) {
printf("%32s | ", func_names[i]);
if (f) fprintf(f, "%s\t", func_names[i]);
for (int j = 0; j < size_count; j++) {
printf(" %s%7.1f\x1b[0m", (passed[i][j])?"":"\x1B[31m", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]);
if (f) fprintf(f, "%.1f\t", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]);
all_passed &= passed[i][j];
}
printf(" |\n");
if (f) fprintf(f, "\n");
}
if (f) fclose(f);
return (all_passed)?SRSLTE_SUCCESS:SRSLTE_ERROR;
}

View File

@ -751,10 +751,37 @@ void srslte_vec_div_fff_simd(float *x, float *y, float *z, int len) {
}
}
int srslte_vec_sc_prod_ccc_simd2(cf_t *x, cf_t h, cf_t *z, int len)
{
int i = 0;
const unsigned int loops = len / 4;
#ifdef HAVE_NEON
simd_cf_t h_vec;
h_vec.val[0] = srslte_simd_f_set1(__real__ h);
h_vec.val[1] = srslte_simd_f_set1(__imag__ h);
for (; i < loops; i++) {
simd_cf_t in = srslte_simd_cfi_load(&x[i*4]);
simd_cf_t temp = srslte_simd_cf_prod(in, h_vec);
srslte_simd_cfi_store(&z[i*4], temp);
}
#endif
i = loops * 4;
return i;
}
void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) {
int i = 0;
#if SRSLTE_SIMD_F_SIZE
#ifdef HAVE_NEON
i = srslte_vec_sc_prod_ccc_simd2(x, h, z, len);
#else
const simd_f_t hre = srslte_simd_f_set1(__real__ h);
const simd_f_t him = srslte_simd_f_set1(__imag__ h);
@ -766,8 +793,8 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) {
simd_f_t sw = srslte_simd_f_swap(temp);
simd_f_t m2 = srslte_simd_f_mul(him, sw);
simd_f_t r = srslte_simd_f_addsub(m1, m2);
srslte_simd_f_store((float *) &z[i], r);
}
} else {
for (; i < len - SRSLTE_SIMD_F_SIZE / 2 + 1; i += SRSLTE_SIMD_F_SIZE / 2) {
@ -782,10 +809,11 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) {
}
}
#endif
#endif
for (; i < len; i++) {
z[i] = x[i] * h;
}
}
void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len) {
@ -831,7 +859,6 @@ void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len) {
simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2);
z1 = srslte_simd_f_sqrt(z1);
srslte_simd_f_store(&z[i], z1);
}
} else {
@ -966,9 +993,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) {
if (SRSLTE_IS_ALIGNED(x)) {
for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) {
simd_f_t a = srslte_simd_f_load(&x[i]);
simd_sel_t res = srslte_simd_f_max(a, simd_max_values);
simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res);
simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res);
simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc);
@ -976,9 +1001,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) {
} else {
for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) {
simd_f_t a = srslte_simd_f_loadu(&x[i]);
simd_sel_t res = srslte_simd_f_max(a, simd_max_values);
simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res);
simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res);
simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc);

View File

@ -381,6 +381,18 @@ bool rlc_am::poll_required()
return true;
if(poll_retx())
return true;
if(tx_sdu_queue.size() == 0 && retx_queue.size() == 0)
return true;
/* According to 5.2.2.1 in 36.322 v13.3.0 a poll should be requested if
* the entire AM window is unacknowledged, i.e. no new PDU can be transmitted.
* However, it seems more appropiate to request more often if polling
* is disabled otherwise, e.g. every N PDUs.
*/
if (cfg.poll_pdu == 0 && cfg.poll_byte == 0 && vt_s % poll_periodicity == 0)
return true;
return false;
}
@ -613,7 +625,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
uint32_t pdu_space = nof_bytes;
uint8_t *pdu_ptr = pdu->msg;
if(pdu_space <= head_len)
if(pdu_space <= head_len + 1)
{
log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n",
rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len);
@ -652,7 +664,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
}
// Pull SDUs from queue
while(pdu_space > head_len && tx_sdu_queue.size() > 0)
while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0)
{
if(last_li > 0)
header.li[header.N_li++] = last_li;

View File

@ -277,8 +277,9 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
int head_len = rlc_um_packed_length(&header);
int pdu_space = nof_bytes;
if(pdu_space <= head_len)
if(pdu_space <= head_len + 1)
{
pool->deallocate(pdu);
log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n",
rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len);
return 0;
@ -309,7 +310,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
}
// Pull SDUs from queue
while(pdu_space > head_len && tx_sdu_queue.size() > 0)
while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0)
{
log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len);
if(last_li > 0)
@ -348,7 +349,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
rlc_um_write_data_pdu_header(&header, pdu);
memcpy(payload, pdu->msg, pdu->N_bytes);
uint32_t ret = pdu->N_bytes;
log->debug("%sreturning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes);
log->debug("%s returning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes);
pool->deallocate(pdu);
debug_state();

View File

@ -18,5 +18,6 @@
# and at http://www.gnu.org/licenses/.
#
add_subdirectory(asn1)
add_subdirectory(common)
add_subdirectory(upper)

View File

@ -0,0 +1,23 @@
#
# Copyright 2013-2017 Software Radio Systems Limited
#
# This file is part of srsLTE
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# srsLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
add_executable(rrc_meas_test rrc_meas_test.cc)
target_link_libraries(rrc_meas_test srslte_common srslte_phy srslte_asn1)
add_test(rrc_meas_test rrc_meas_test)

View File

@ -0,0 +1,91 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <assert.h>
#include <iostream>
#include <srslte/srslte.h>
#include "srslte/common/log_filter.h"
#include "srslte/asn1/liblte_rrc.h"
void basic_test() {
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
LIBLTE_BIT_MSG_STRUCT bit_buf;
LIBLTE_BIT_MSG_STRUCT bit_buf2;
LIBLTE_BYTE_MSG_STRUCT byte_buf;
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
uint32_t rrc_message_len = 18;
uint8_t rrc_message[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83,
0xC0, 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01,
0xBC, 0x48};
srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8);
bit_buf.N_bits = rrc_message_len*8;
liblte_rrc_unpack_ul_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &ul_dcch_msg);
assert(ul_dcch_msg.msg_type == LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT);
LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *rep = &ul_dcch_msg.msg.measurement_report;
assert(rep->meas_id == 1);
assert(rep->pcell_rsrp_result == 73);
assert(rep->pcell_rsrq_result == 15);
assert(rep->have_meas_result_neigh_cells);
assert(rep->meas_result_neigh_cells_choice == LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA);
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT *eutra = &rep->meas_result_neigh_cells.eutra;
assert(eutra->n_result == 1);
assert(eutra->result_eutra_list[0].phys_cell_id == 357);
assert(eutra->result_eutra_list[0].have_cgi_info);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mcc == 0xF898);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mnc == 0xFF78);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.cell_id == 0x1084104);
assert(eutra->result_eutra_list[0].cgi_info.tracking_area_code == 0x1042);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.n_plmn_identity_list == 1);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mcc == 0xFFFF);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mnc == 0xFF00);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrp_result == 60);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrq_result == 18);
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT*)&bit_buf2);
srslte_bit_pack_vector(bit_buf2.msg, byte_buf.msg, bit_buf2.N_bits);
byte_buf.N_bytes = (bit_buf2.N_bits+7)/8;
log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "UL_DCCH Packed message\n");
for(uint32_t i=0; i<rrc_message_len; i++) {
assert(byte_buf.msg[i] == rrc_message[i]);
}
}
int main(int argc, char **argv) {
basic_test();
}

View File

@ -123,7 +123,7 @@ void basic_test()
byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++)
{
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 3 bytes for header + payload
len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len;
}
@ -351,7 +351,7 @@ void retx_test()
byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++)
{
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 2 byte header + 1 byte payload
len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 2 byte header + 1 byte payload
pdu_bufs[i].N_bytes = len;
}

View File

@ -123,7 +123,7 @@ void basic_test()
byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++)
{
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 3 bytes for header + payload
len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len;
}
@ -191,7 +191,7 @@ void loss_test()
byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++)
{
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 3 bytes for header + payload
len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len;
}

View File

@ -87,8 +87,8 @@ private:
bool initiated;
bool running;
cf_t *signal_buffer_rx;
cf_t *signal_buffer_tx;
cf_t *signal_buffer_rx;
cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS];
uint32_t tti_rx, tti_tx_dl, tti_tx_ul;
uint32_t sf_rx, sf_tx, tx_mutex_cnt;
uint32_t t_rx, t_tx_dl, t_tx_ul;

View File

@ -749,7 +749,7 @@ int enb::parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_
}
// Fill rest of data from enb config
sib1->cell_id = args->enb.s1ap.enb_id;
sib1->cell_id = (args->enb.s1ap.enb_id << 8) + args->enb.s1ap.cell_id;
sib1->tracking_area_code = args->enb.s1ap.tac;
sib1->freq_band_indicator = srslte_band_get_band(args->rf.dl_earfcn);
sib1->N_plmn_ids = 1;

View File

@ -597,12 +597,13 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
uint16_t rnti = (uint16_t) iter->first;
dl_harq_proc *h = dl_metric->get_user_allocation(user);
uint32_t aggr_level = user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports));
if (h) {
// Try to schedule DCI first
if (generate_dci(&data[nof_data_elems].dci_location,
user->get_locations(current_cfi, sf_idx),
user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)), user))
user->get_locations(current_cfi, sf_idx),
aggr_level, user))
{
bool is_newtx = h->is_empty();
int tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi);
@ -620,7 +621,8 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
}
} else {
h->reset();
Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id());
Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d, L=%d, nof_candidates=%d\n",
rnti, h->get_id(), aggr_level, user->get_locations(current_cfi, sf_idx)->nof_loc[aggr_level] );
}
}
}

View File

@ -93,12 +93,13 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error allocating memory\n");
return;
}
signal_buffer_tx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t));
if (!signal_buffer_tx) {
bzero(&signal_buffer_tx, sizeof(cf_t *) * SRSLTE_MAX_PORTS);
signal_buffer_tx[0] = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t));
if (!signal_buffer_tx[0]) {
fprintf(stderr, "Error allocating memory\n");
return;
}
if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) {
if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB DL\n");
return;
}
@ -106,7 +107,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error initiating ENB DL\n");
return;
}
if (srslte_enb_ul_init(&enb_ul, phy->cell.nof_prb)) {
if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB UL\n");
return;
}
@ -156,8 +157,10 @@ void phch_worker::stop()
if (signal_buffer_rx) {
free(signal_buffer_rx);
}
if (signal_buffer_tx) {
free(signal_buffer_tx);
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (signal_buffer_tx[i]) {
free(signal_buffer_tx[i]);
}
}
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
@ -338,9 +341,9 @@ void phch_worker::work_imp()
}
// Generate signal and transmit
srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx);
srslte_enb_dl_gen_signal(&enb_dl);
Debug("Sending to radio\n");
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
phy->worker_end(tx_mutex_cnt, signal_buffer_tx[0], SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
#ifdef DEBUG_WRITE_FILE
fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t), 1, f);
@ -408,7 +411,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
srslte_ra_ul_grant_t phy_grant;
int res = -1;
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti_rx%8)) {
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant)) {
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
phy_grant.mcs.mod = SRSLTE_MOD_16QAM;
}

View File

@ -768,9 +768,9 @@ bool rrc::ue::is_timeout()
}
if (deadline_str) {
uint64_t deadline = deadline_s*1e6 + deadline_us;
uint64_t elapsed = t[0].tv_sec*1e6 + t[0].tv_usec;
if (elapsed > deadline) {
int64_t deadline = deadline_s*1e6 + deadline_us;
int64_t elapsed = t[0].tv_sec*1e6 + t[0].tv_usec;
if (elapsed > deadline && elapsed > 0) {
parent->rrc_log->warning("User rnti=0x%x expired %s deadline: %d:%d>%d:%d us\n",
rnti, deadline_str,
t[0].tv_sec, t[0].tv_usec,

View File

@ -41,14 +41,16 @@ namespace srsue {
class demux : public srslte::pdu_queue::process_callback
{
public:
demux(uint8_t nof_harq_proc_);
demux();
void init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers::timer* time_alignment_timer);
bool process_pdus();
uint8_t* request_buffer(uint32_t pid, uint32_t len);
uint8_t* request_buffer(uint32_t len);
uint8_t* request_buffer_bcch(uint32_t len);
void deallocate(uint8_t* payload_buffer_ptr);
void push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp);
void push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp);
void push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp);
void push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes);
void set_uecrid_callback(bool (*callback)(void*, uint64_t), void *arg);
@ -59,7 +61,8 @@ public:
private:
const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps
const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid
uint8_t bcch_buffer[1024]; // BCCH PID has a dedicated buffer
const static int MAX_BCCH_PDU_LEN = 1024;
uint8_t bcch_buffer[MAX_BCCH_PDU_LEN]; // BCCH PID has a dedicated buffer
bool (*uecrid_callback) (void*, uint64_t);
void *uecrid_callback_arg;
@ -76,8 +79,7 @@ private:
srslte::log *log_h;
srslte::timers::timer *time_alignment_timer;
rlc_interface_mac *rlc;
uint8_t nof_harq_proc;
// Buffer of PDUs
srslte::pdu_queue pdus;
};

View File

@ -259,13 +259,16 @@ private:
memcpy(&cur_grant, &grant, sizeof(Tgrant));
// If data has not yet been successfully decoded
if (!ack) {
if (!ack || (grant.rv[tid]==0 && grant.phy_grant.dl.mcs[tid].idx < 29)) {
// Instruct the PHY To combine the received data and attempt to decode it
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid,
cur_grant.n_bytes[tid]);
if (pid == HARQ_BCCH_PID) {
payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]);
} else {
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(cur_grant.n_bytes[tid]);
}
action->payload_ptr[tid] = payload_buffer_ptr;
if (!action->payload_ptr) {
if (!action->payload_ptr[tid]) {
action->decode_enabled[tid] = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]);
return;
@ -305,8 +308,7 @@ private:
harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes[tid], ack, cur_grant.tti);
}
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes[tid]);
harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid],
cur_grant.tti);
harq_entity->demux_unit->push_pdu_bcch(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti);
} else {
if (harq_entity->pcap) {
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack,
@ -318,8 +320,7 @@ private:
harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]);
} else {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]);
harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid],
cur_grant.tti);
harq_entity->demux_unit->push_pdu(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti);
// Compute average number of retransmissions per packet
harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx,
@ -346,9 +347,10 @@ private:
// Determine if it's a new transmission 5.3.2.2
bool calc_is_new_transmission(Tgrant grant) {
if ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed)
(pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission)
is_first_tb) // 3rd condition (first TB)
if (grant.phy_grant.dl.mcs[tid].idx <= 28 && // mcs 29,30,31 always retx regardless of rest
((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed)
(pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission)
is_first_tb))
{
is_first_tb = false;
is_new_transmission = true;

View File

@ -48,12 +48,14 @@ class metrics_csv : public srslte::metrics_listener<ue_metrics_t>
public:
metrics_csv(std::string filename);
void set_metrics(ue_metrics_t &m, float report_period_secs);
void set_periodicity(float metrics_report_period_sec);
void set_metrics(ue_metrics_t &m);
void set_ue_handle(ue_metrics_interface *ue_);
private:
std::string float_to_string(float f, int digits, bool add_semicolon = true);
float metrics_report_period;
std::ofstream file;
ue_metrics_interface* ue;
uint32_t n_reports;

View File

@ -46,8 +46,9 @@ class metrics_stdout : public srslte::metrics_listener<ue_metrics_t>
public:
metrics_stdout();
void set_periodicity(float metrics_report_period_sec);
void toggle_print(bool b);
void set_metrics(ue_metrics_t &m, float report_period_secs);
void set_metrics(ue_metrics_t &m);
void set_ue_handle(ue_metrics_interface *ue_);
private:
@ -55,6 +56,7 @@ private:
std::string float_to_eng_string(float f, int digits);
std::string int_to_eng_string(int f, int digits);
float metrics_report_period;
bool do_print;
uint8_t n_reports;
ue_metrics_interface* ue;

View File

@ -149,7 +149,12 @@ private:
uint32_t I_sr;
float cfo;
bool rar_cqi_request;
// Save last TBS for mcs>28 cases
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
int last_ul_tbs[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
// Metrics
dl_metrics_t dl_metrics;
ul_metrics_t ul_metrics;

View File

@ -103,6 +103,7 @@ typedef struct {
}gui_args_t;
typedef struct {
std::string ip_netmask;
phy_args_t phy;
float metrics_period_secs;
bool pregenerate_signals;

View File

@ -57,8 +57,13 @@ public:
// NAS interface
srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str);
void set_netmask(std::string netmask);
private:
bool default_netmask;
std::string netmask;
static const int GW_THREAD_PRIO = 7;
pdcp_interface_gw *pdcp;

View File

@ -98,6 +98,8 @@ private:
uint8_t transaction_id;
bool drb_up;
bool reestablishment_in_progress;
// timeouts in ms
uint32_t connecting_timeout;
@ -244,7 +246,8 @@ private:
// Helpers
void rrc_connection_release();
void radio_link_failure();
void con_restablish_cell_reselected();
void radio_link_failure();
static void* start_sib_thread(void *rrc_);
void sib_search();
void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2);

View File

@ -36,7 +36,7 @@
namespace srsue {
demux::demux(uint8_t nof_harq_proc_) : mac_msg(20), pending_mac_msg(20), nof_harq_proc(nof_harq_proc_)
demux::demux() : mac_msg(20), pending_mac_msg(20), rlc(NULL)
{
}
@ -64,18 +64,18 @@ void demux::deallocate(uint8_t* payload_buffer_ptr)
pdus.deallocate(payload_buffer_ptr);
}
}
uint8_t* demux::request_buffer(uint32_t pid, uint32_t len)
{
uint8_t *buff = NULL;
if (pid < nof_harq_proc) {
return pdus.request(len);
} else if (pid == nof_harq_proc) {
buff = bcch_buffer;
uint8_t* demux::request_buffer_bcch(uint32_t len)
{
if (len < MAX_BCCH_PDU_LEN) {
return bcch_buffer;
} else {
Error("Requested buffer for invalid PID=%d\n", pid);
return NULL;
}
return buff;
}
uint8_t* demux::request_buffer(uint32_t len)
{
return pdus.request(len);
}
/* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will
@ -117,21 +117,17 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes)
* This function enqueues the packet and returns quicly because ACK
* deadline is important here.
*/
void demux::push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp)
{
if (pid < nof_harq_proc) {
return pdus.push(buff, nof_bytes, tstamp);
} else if (pid == nof_harq_proc) {
/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through
* the MAC in transparent mode.
* Warning: In this case function sends the message to RLC now, since SI blocks do not
* require ACK feedback to be transmitted quickly.
*/
Debug("Pushed BCCH MAC PDU in transparent mode\n");
rlc->write_pdu_bcch_dlsch(buff, nof_bytes);
} else {
Error("Pushed buffer for invalid PID=%d\n", pid);
}
void demux::push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
return pdus.push(buff, nof_bytes, tstamp);
}
/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through
* the MAC in transparent mode.
* Warning: In this case function sends the message to RLC now, since SI blocks do not
* require ACK feedback to be transmitted quickly.
*/
void demux::push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
rlc->write_pdu_bcch_dlsch(buff, nof_bytes);
}
bool demux::process_pdus()

View File

@ -44,7 +44,6 @@ namespace srsue {
mac::mac() : ttisync(10240),
timers(64),
mux_unit(MAC_NOF_HARQ_PROC),
demux_unit(SRSLTE_MAX_TB*MAC_NOF_HARQ_PROC),
pdu_process_thread(&demux_unit)
{
started = false;
@ -118,7 +117,8 @@ void mac::reset()
Info("Resetting MAC\n");
timers.stop_all();
timers.get(timer_alignment)->stop();
timers.get(contention_resolution_timer)->stop();
ul_harq.reset_ndi();

View File

@ -122,6 +122,10 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
/* Expert section */
("expert.ip_netmask",
bpo::value<string>(&args->expert.ip_netmask)->default_value("255.255.255.0"),
"Netmask of the tun_srsue device")
("expert.phy.worker_cpu_mask",
bpo::value<int>(&args->expert.phy.worker_cpu_mask)->default_value(-1),
"cpu bit mask (eg 255 = 1111 1111)")
@ -198,6 +202,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::value<float>(&args->expert.phy.cfo_correct_tol_hz)->default_value(50.0),
"Tolerance (in Hz) for digial CFO compensation.")
("expert.cfo_ema",
bpo::value<float>(&args->expert.phy.cfo_ema)->default_value(0.4),
"CFO Exponential Moving Average coefficient. Lower makes it more robust to noise "
"but vulnerable to periodic interruptions due to VCO corrections.")
("expert.time_correct_period",
bpo::value<int>(&args->expert.phy.time_correct_period)->default_value(5),
"Period for sampling time offset correction.")
@ -377,11 +386,13 @@ int main(int argc, char *argv[])
metricshub.init(ue, args.expert.metrics_period_secs);
metricshub.add_listener(&metrics_screen);
metrics_screen.set_ue_handle(ue);
metrics_screen.set_periodicity(args.expert.metrics_period_secs);
metrics_csv metrics_file(args.expert.metrics_csv_filename);
if (args.expert.metrics_csv_enable) {
metricshub.add_listener(&metrics_file);
metrics_file.set_ue_handle(ue);
metrics_file.set_periodicity(args.expert.metrics_period_secs);
}
pthread_t input;

View File

@ -43,6 +43,7 @@ namespace srsue{
metrics_csv::metrics_csv(std::string filename)
:n_reports(0)
,metrics_report_period(1.0)
,ue(NULL)
{
file.open(filename.c_str());
@ -53,7 +54,11 @@ void metrics_csv::set_ue_handle(ue_metrics_interface *ue_)
ue = ue_;
}
void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period)
void metrics_csv::set_periodicity(float metrics_report_period_sec) {
this->metrics_report_period = metrics_report_period_sec;
}
void metrics_csv::set_metrics(ue_metrics_t &metrics)
{
if (file.is_open() && ue != NULL) {
if(n_reports == 0) {
@ -75,7 +80,7 @@ void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period
file << float_to_string(metrics.phy.ul.mcs, 2);
file << float_to_string((float) metrics.mac.ul_buffer, 2);
file << float_to_string((float) metrics.mac.tx_brate/metrics_report_period, 2);
if (metrics.mac.tx_pkts > 0) {
if (metrics.mac.tx_pkts > 0) {
file << float_to_string((float) 100*metrics.mac.tx_errors/metrics.mac.tx_pkts, 1);
} else {
file << float_to_string(0, 2);

View File

@ -50,6 +50,7 @@ char const * const prefixes[2][9] =
metrics_stdout::metrics_stdout()
:do_print(false)
,n_reports(10)
,metrics_report_period(1.0)
,ue(NULL)
{
}
@ -64,8 +65,11 @@ void metrics_stdout::toggle_print(bool b)
do_print = b;
}
void metrics_stdout::set_periodicity(float metrics_report_period_sec) {
this->metrics_report_period = metrics_report_period_sec;
}
void metrics_stdout::set_metrics(ue_metrics_t &metrics, float metrics_report_period)
void metrics_stdout::set_metrics(ue_metrics_t &metrics)
{
if(!do_print || ue == NULL)
return;

View File

@ -336,6 +336,7 @@ void phch_common::reset_ul()
pthread_mutex_trylock(&tx_mutex[i]);
pthread_mutex_unlock(&tx_mutex[i]);
}
radio_h->tx_end();
}
}

View File

@ -65,8 +65,7 @@ phch_worker::phch_worker() : tr_exec(10240)
cell_initiated = false;
pregen_enabled = false;
trace_enabled = false;
reset();
reset();
}
@ -97,7 +96,7 @@ void phch_worker::reset()
bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t));
I_sr = 0;
rnti_is_set = false;
rar_cqi_request = false;
rar_cqi_request = false;
cfi = 0;
}
@ -118,12 +117,12 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h)
}
}
if (srslte_ue_dl_init(&ue_dl, max_prb, phy->args->nof_rx_ant)) {
if (srslte_ue_dl_init(&ue_dl, signal_buffer, max_prb, phy->args->nof_rx_ant)) {
Error("Initiating UE DL\n");
return false;
}
if (srslte_ue_ul_init(&ue_ul, max_prb)) {
if (srslte_ue_ul_init(&ue_ul, signal_buffer[0], max_prb)) {
Error("Initiating UE UL\n");
return false;
}
@ -479,10 +478,20 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
return false;
}
grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS));
// Set last TBS for this TB (pid) in case of mcs>29 (7.1.7.2 of 36.213)
for (int i=0;i<SRSLTE_MAX_CODEWORDS;i++) {
if (grant->phy_grant.dl.mcs[i].tbs < 0) {
grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i];
}
// save it
last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs;
}
/* Fill MAC grant structure */
grant->ndi[0] = dci_unpacked.ndi;
grant->ndi[1] = dci_unpacked.ndi_1;
grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS));
grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8;
grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8;
grant->tti = tti;
@ -495,11 +504,6 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
grant->tb_en[1] = dci_unpacked.tb_en[1];
grant->tb_cw_swap = dci_unpacked.tb_cw_swap; // FIXME: tb_cw_swap not supported
if (grant->tb_cw_swap) {
Info("tb_cw_swap = true\n");
printf("tb_cw_swap = true\n");
}
last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl);
char hexstr[16];
@ -624,7 +628,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
for (int i=0;i<SRSLTE_MAX_CODEWORDS;i++) {
if (grant->tb_en[i]) {
snprintf(tbstr[i], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d",
snprintf(tbstr[i], 128, ", CW%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d",
i, grant->mcs[i].tbs/8, grant->mcs[i].idx, rv[i], acks[i] ? "OK" : "KO",
srslte_pdsch_last_noi_cw(&ue_dl.pdsch, i));
}
@ -719,14 +723,29 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
ue_dl.last_location_ul.ncce, (1<<ue_dl.last_location_ul.L), dci_msg.nof_bits, hexstr);
if (grant->phy_grant.ul.mcs.tbs==0) {
srslte_vec_fprint_hex(stdout, dci_msg.data, dci_msg.nof_bits);
Info("Received PUSCH grant with empty data\n");
}
}
}
if (ret) {
// Use last TBS for this TB in case of mcs>28
if (grant->phy_grant.ul.mcs.tbs < 0) {
grant->phy_grant.ul.mcs.tbs = last_ul_tbs[tti%(2*HARQ_DELAY_MS)];
}
last_ul_tbs[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs;
if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_LAST) {
grant->phy_grant.ul.mcs.mod = last_ul_mod[tti%(2*HARQ_DELAY_MS)];
grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod);
}
last_ul_mod[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod;
}
/* Limit UL modulation if not supported by the UE or disabled by higher layers */
if (!phy->config->enable_64qam) {
if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_64QAM) {
if (grant->phy_grant.ul.mcs.mod >= SRSLTE_MOD_64QAM) {
grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM;
grant->phy_grant.ul.Qm = 4;
}
@ -899,7 +918,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
if (srslte_ue_ul_cfg_grant(&ue_ul, grant, TTI_TX(tti), rv, current_tx_nb)) {
Error("Configuring UL grant\n");
}
if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul,
payload, uci_data,
softbuffer,
@ -926,12 +945,12 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
#endif
Info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n",
(tti+4)%10240,
grant->n_prb[0], grant->n_prb[0]+grant->L_prb,
grant->mcs.tbs/8, grant->mcs.idx, rv,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
cfo*15, timestr);
(tti+HARQ_DELAY_MS)%10240,
grant->n_prb[0], grant->n_prb[0]+grant->L_prb,
grant->mcs.tbs/8, grant->mcs.idx, rv,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
cfo*15, timestr);
// Store metrics
ul_metrics.mcs = grant->mcs.idx;

View File

@ -200,8 +200,8 @@ void phy::set_timeadv_rar(uint32_t ta_cmd) {
void phy::set_timeadv(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new(n_ta, ta_cmd);
//sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS);
Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS);
//Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
}
void phy::configure_prach_params()
@ -313,7 +313,8 @@ void phy::reset()
pdcch_dl_search_reset();
for(uint32_t i=0;i<nof_workers;i++) {
workers[i].reset();
}
}
workers_common.reset_ul();
}
uint32_t phy::get_current_tti()

View File

@ -185,6 +185,8 @@ bool ue::init(all_args_t *args_)
nas.init(&usim, &rrc, &gw, &nas_log, 1 /* RB_ID_SRB1 */);
gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */);
gw.set_netmask(args->expert.ip_netmask);
rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log);
rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str()));

View File

@ -44,6 +44,7 @@ gw::gw()
:if_up(false)
{
current_ip_addr = 0;
default_netmask = true;
}
void gw::init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, uint32_t lcid_)
@ -104,6 +105,12 @@ void gw::get_metrics(gw_metrics_t &m)
ul_tput_bytes = 0;
}
void gw::set_netmask(std::string netmask) {
default_netmask = false;
this->netmask = netmask;
}
/*******************************************************************************
PDCP interface
*******************************************************************************/
@ -152,7 +159,11 @@ srslte::error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str)
return(srslte::ERROR_CANT_START);
}
ifr.ifr_netmask.sa_family = AF_INET;
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0");
const char *mask = "255.255.255.0";
if (!default_netmask) {
mask = netmask.c_str();
}
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(mask);
if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr))
{
err_str = strerror(errno);

View File

@ -281,7 +281,6 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept;
nas_log->info("Received Attach Accept\n");
count_dl++;
liblte_mme_unpack_attach_accept_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_accept);
@ -359,6 +358,8 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
state = EMM_STATE_REGISTERED;
current_plmn = selecting_plmn;
count_dl++;
// Send EPS bearer context accept and attach complete
count_ul++;
act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id;
@ -437,6 +438,9 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->console("Warning: Network authentication failure\n");
pool->deallocate(pdu);
}
// Reset DL counter (as per 24.301 5.4.3.2)
count_dl = 0;
}
void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) {
@ -539,6 +543,8 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) {
}
}
count_dl++;
if (!success) {
// Reuse pdu for response
pdu->reset();

View File

@ -35,8 +35,6 @@
#include "srslte/common/security.h"
#include "srslte/common/bcd_helpers.h"
#define TIMEOUT_RESYNC_REESTABLISH 100
using namespace srslte;
namespace srsue {
@ -92,6 +90,8 @@ void rrc::init(phy_interface_rrc *phy_,
pthread_mutex_init(&mutex, NULL);
reestablishment_in_progress = false;
ue_category = SRSLTE_UE_CATEGORY;
t301 = mac_timers->timer_get_unique_id();
t310 = mac_timers->timer_get_unique_id();
@ -207,7 +207,11 @@ void rrc::run_thread() {
break;
case RRC_STATE_CELL_SELECTED:
rrc_log->info("RRC Cell Selected: Sending connection request...\n");
send_con_request();
if (reestablishment_in_progress) {
con_restablish_cell_reselected();
} else {
send_con_request();
}
state = RRC_STATE_CONNECTING;
connecting_timeout = 0;
break;
@ -226,6 +230,7 @@ void rrc::run_thread() {
usleep(60000);
rrc_log->info("Leaving RRC_CONNECTED state\n");
drb_up = false;
reestablishment_in_progress = false;
pdcp->reset();
rlc->reset();
phy->reset();
@ -484,12 +489,12 @@ void rrc::earfcn_end() {
// Detection of physical layer problems (5.3.11.1)
void rrc::out_of_sync() {
current_cell->in_sync = false;
current_cell->in_sync = false;
if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) {
n310_cnt++;
if (n310_cnt == N310) {
// attempt resync
phy->sync_reset();
//phy->sync_reset();
mac_timers->timer_get(t310)->reset();
mac_timers->timer_get(t310)->run();
@ -663,6 +668,8 @@ void rrc::send_con_restablish_request() {
ul_ccch_msg.msg.rrc_con_reest_req.cause = LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE;
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
reestablishment_in_progress = true;
rrc_log->info("Initiating RRC Connection Reestablishment Procedure\n");
rrc_log->console("RRC Connection Reestablishment\n");
mac_timers->timer_get(t310)->stop();
@ -673,19 +680,16 @@ void rrc::send_con_restablish_request() {
set_phy_default();
mac->reset();
set_mac_default();
}
// FIXME: Cell selection should be different??
// Wait for cell re-synchronization
uint32_t timeout_cnt = 0;
while (!phy->sync_status() && timeout_cnt < TIMEOUT_RESYNC_REESTABLISH) {
usleep(10000);
timeout_cnt++;
}
// Actions following cell reselection 5.3.7.3
void rrc::con_restablish_cell_reselected()
{
reestablishment_in_progress = false;
rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n");
mac_timers->timer_get(t301)->reset();
mac_timers->timer_get(t301)->run();
mac_timers->timer_get(t311)->stop();
rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n");
// Byte align and pack the message bits for PDCP
if ((bit_buf.N_bits % 8) != 0) {

View File

@ -98,7 +98,11 @@ enable = false
#####################################################################
# Expert configuration options
#
# ue_category: Sets UE category (range 1-5). Default: 4
# ue_category: Sets UE category (range 1-5). Default: 4
# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0
# rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but
# can cause UHD instability for long-duration testing. Default true.
# ue_category: Sets UE category (range 1-5). Default: 4
#
# prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only.,
# Default is to use tx_gain in [rf] section.
@ -115,7 +119,9 @@ enable = false
# nof_phy_threads: Selects the number of PHY threads (maximum 4, minimum 1, default 2)
# equalizer_mode: Selects equalizer mode. Valid modes are: "mmse", "zf" or any
# non-negative real number to indicate a regularized zf coefficient.
# Default is MMSE.
# Default is MMSE.
# cfo_ema: CFO Exponential Moving Average coefficient. Lower makes it more robust to noise
# but vulnerable to periodic interruptions due to VCO corrections.
# cfo_integer_enabled: Enables integer CFO estimation and correction. This needs improvement
# and may lead to incorrect synchronization. Use with caution.
# cfo_correct_tol_hz: Tolerance (in Hz) for digial CFO compensation. Lower tolerance means that
@ -138,6 +144,8 @@ enable = false
#
#####################################################################
[expert]
#ip_netmask = 255.255.255.0
#rssi_sensor_enabled = false
#ue_category = 4
#prach_gain = 30
#cqi_max = 15
@ -148,6 +156,7 @@ enable = false
#attach_enable_64qam = false
#nof_phy_threads = 2
#equalizer_mode = mmse
#cfo_ema = 0.4
#cfo_integer_enabled = false
#cfo_correct_tol_hz = 50
#time_correct_period = 5