diff --git a/CHANGELOG b/CHANGELOG index 9bed0247c..7a3a03e8a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ Change Log for Releases ============================== +## 18.03.1 + * Fixed compilation for NEON + * Fixed logging and RLC AM issue + ## 18.03 * Many bug-fixes and improved stability and performance in all parts diff --git a/cmake/modules/SRSLTEVersion.cmake b/cmake/modules/SRSLTEVersion.cmake index 30d2707b0..11b2e79e9 100644 --- a/cmake/modules/SRSLTEVersion.cmake +++ b/cmake/modules/SRSLTEVersion.cmake @@ -20,5 +20,5 @@ SET(SRSLTE_VERSION_MAJOR 18) SET(SRSLTE_VERSION_MINOR 3) -SET(SRSLTE_VERSION_PATCH 0) +SET(SRSLTE_VERSION_PATCH 1) SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") diff --git a/lib/include/srslte/asn1/liblte_common.h b/lib/include/srslte/asn1/liblte_common.h index 21d962748..3b7eccf6f 100644 --- a/lib/include/srslte/asn1/liblte_common.h +++ b/lib/include/srslte/asn1/liblte_common.h @@ -51,9 +51,11 @@ // FIXME: This was chosen arbitrarily #define LIBLTE_ASN1_OID_MAXSUBIDS 128 + +// Caution these values must match SRSLTE_ ones in common.h #define LIBLTE_MAX_MSG_SIZE_BITS 102048 #define LIBLTE_MAX_MSG_SIZE_BYTES 12756 -#define LIBLTE_MSG_HEADER_OFFSET 1024 +#define LIBLTE_MSG_HEADER_OFFSET 1020 /******************************************************************************* TYPEDEFS @@ -82,6 +84,8 @@ static const char liblte_error_text[LIBLTE_ERROR_N_ITEMS][64] = { "Decode failure", }; +#define LIBLTE_STRING_LEN 128 + typedef void* LIBLTE_ASN1_OPEN_TYPE_STRUCT; typedef struct { @@ -96,86 +100,15 @@ typedef struct{ typedef struct{ uint32 N_bits; + uint8 header[LIBLTE_MSG_HEADER_OFFSET]; uint8 msg[LIBLTE_MAX_MSG_SIZE_BITS]; -}LIBLTE_SIMPLE_BIT_MSG_STRUCT; +}LIBLTE_BIT_MSG_STRUCT; typedef struct{ uint32 N_bytes; + uint8 header[LIBLTE_MSG_HEADER_OFFSET]; uint8 msg[LIBLTE_MAX_MSG_SIZE_BYTES]; -}LIBLTE_SIMPLE_BYTE_MSG_STRUCT; - - -struct LIBLTE_BYTE_MSG_STRUCT{ - uint32 N_bytes; - uint8 buffer[LIBLTE_MAX_MSG_SIZE_BYTES]; - uint8 *msg; - - LIBLTE_BYTE_MSG_STRUCT():N_bytes(0) - { - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - } - LIBLTE_BYTE_MSG_STRUCT(const LIBLTE_BYTE_MSG_STRUCT& buf) - { - N_bytes = buf.N_bytes; - memcpy(msg, buf.msg, N_bytes); - } - LIBLTE_BYTE_MSG_STRUCT & operator= (const LIBLTE_BYTE_MSG_STRUCT & buf) - { - // avoid self assignment - if (&buf == this) - return *this; - N_bytes = buf.N_bytes; - memcpy(msg, buf.msg, N_bytes); - return *this; - } - uint32 get_headroom() - { - return msg-buffer; - } - void reset() - { - N_bytes = 0; - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - } -}; - -struct LIBLTE_BIT_MSG_STRUCT{ - uint32 N_bits; - uint8 buffer[LIBLTE_MAX_MSG_SIZE_BITS]; - uint8 *msg; - - LIBLTE_BIT_MSG_STRUCT():N_bits(0) - { - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - while( (uint64_t)(msg) % 8 > 0) { - msg++; - } - } - LIBLTE_BIT_MSG_STRUCT(const LIBLTE_BIT_MSG_STRUCT& buf){ - N_bits = buf.N_bits; - memcpy(msg, buf.msg, N_bits); - } - LIBLTE_BIT_MSG_STRUCT & operator= (const LIBLTE_BIT_MSG_STRUCT & buf){ - // avoid self assignment - if (&buf == this) - return *this; - N_bits = buf.N_bits; - memcpy(msg, buf.msg, N_bits); - return *this; - } - uint32 get_headroom() - { - return msg-buffer; - } - void reset() - { - N_bits = 0; - msg = &buffer[LIBLTE_MSG_HEADER_OFFSET]; - while( (uint64_t)(msg) % 8 > 0) { - msg++; - } - } -}; +}LIBLTE_BYTE_MSG_STRUCT; /******************************************************************************* diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 31b1a49df..4a168bca2 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -1209,7 +1209,7 @@ static const char liblte_mme_add_ci_text[LIBLTE_MME_ADD_CI_N_ITEMS][20] = {"Don' "Add"}; // Structs typedef struct{ - std::string name; + char name[LIBLTE_STRING_LEN]; LIBLTE_MME_ADD_CI_ENUM add_ci; }LIBLTE_MME_NETWORK_NAME_STRUCT; // Functions @@ -1752,7 +1752,7 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8 **ie_ // Enums // Structs typedef struct{ - std::string apn; + char apn[LIBLTE_STRING_LEN]; }LIBLTE_MME_ACCESS_POINT_NAME_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn, diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index 4fdff34e2..22038d130 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -5579,7 +5579,7 @@ static const char liblte_rrc_ul_information_transfer_type_text[LIBLTE_RRC_UL_INF "CDMA2000-HRPD"}; // Structs typedef struct{ - LIBLTE_SIMPLE_BYTE_MSG_STRUCT dedicated_info; + LIBLTE_BYTE_MSG_STRUCT dedicated_info; LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_ENUM dedicated_info_type; }LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT; // Functions @@ -5960,7 +5960,7 @@ typedef struct{ }LIBLTE_RRC_REGISTERED_MME_STRUCT; typedef struct{ LIBLTE_RRC_REGISTERED_MME_STRUCT registered_mme; - LIBLTE_SIMPLE_BYTE_MSG_STRUCT dedicated_info_nas; + LIBLTE_BYTE_MSG_STRUCT dedicated_info_nas; uint8 rrc_transaction_id; uint8 selected_plmn_id; bool registered_mme_present; @@ -6245,7 +6245,7 @@ typedef struct{ typedef struct{ LIBLTE_RRC_MEAS_CONFIG_STRUCT meas_cnfg; LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT mob_ctrl_info; - LIBLTE_SIMPLE_BYTE_MSG_STRUCT ded_info_nas_list[LIBLTE_RRC_MAX_DRB]; + LIBLTE_BYTE_MSG_STRUCT ded_info_nas_list[LIBLTE_RRC_MAX_DRB]; LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT rr_cnfg_ded; LIBLTE_RRC_SECURITY_CONFIG_HO_STRUCT sec_cnfg_ho; uint32 N_ded_info_nas; @@ -6626,7 +6626,7 @@ static const char liblte_rrc_dl_information_transfer_type_text[LIBLTE_RRC_DL_INF "CDMA2000-HRPD"}; // Structs typedef struct{ - LIBLTE_SIMPLE_BYTE_MSG_STRUCT dedicated_info; + LIBLTE_BYTE_MSG_STRUCT dedicated_info; LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_ENUM dedicated_info_type; uint8 rrc_transaction_id; }LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT; diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 754b7423d..b7130f6d5 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -61,7 +61,7 @@ // 3GPP 36.306 Table 4.1.1 #define SRSLTE_MAX_BUFFER_SIZE_BITS 102048 #define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756 -#define SRSLTE_BUFFER_HEADER_OFFSET 1024 +#define SRSLTE_BUFFER_HEADER_OFFSET 1020 #define SRSLTE_BUFFER_POOL_LOG_ENABLED @@ -116,15 +116,17 @@ public: byte_buffer_t():N_bytes(0) { - timestamp_is_set = false; + bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); + timestamp_is_set = false; msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET]; next = NULL; #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED - debug_name[0] = 0; + bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN); #endif } byte_buffer_t(const byte_buffer_t& buf) { + bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); N_bytes = buf.N_bytes; memcpy(msg, buf.msg, N_bytes); } @@ -133,6 +135,7 @@ public: // avoid self assignment if (&buf == this) return *this; + bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES); N_bytes = buf.N_bytes; memcpy(msg, buf.msg, N_bytes); return *this; diff --git a/lib/include/srslte/common/pdu_queue.h b/lib/include/srslte/common/pdu_queue.h index a0c2b1da9..5866ce3b3 100644 --- a/lib/include/srslte/common/pdu_queue.h +++ b/lib/include/srslte/common/pdu_queue.h @@ -41,29 +41,35 @@ namespace srslte { class pdu_queue { public: + typedef enum { + DCH, + BCH, + MCH + } channel_t; class process_callback { - public: - virtual void process_pdu(uint8_t *buff, uint32_t len, uint32_t tstamp) = 0; + public: + virtual void process_pdu(uint8_t *buff, uint32_t len, channel_t channel, uint32_t tstamp) = 0; }; pdu_queue(uint32_t pool_size = DEFAULT_POOL_SIZE) : pool(pool_size), callback(NULL), log_h(NULL) {} void init(process_callback *callback, log* log_h_); - uint8_t* request(uint32_t len); + uint8_t* request(uint32_t len); void deallocate(uint8_t* pdu); - void push(uint8_t *ptr, uint32_t len, uint32_t tstamp = 0); - + void push(uint8_t *ptr, uint32_t len, channel_t channel = DCH, uint32_t tstamp = 0); + bool process_pdus(); - + private: - const static int DEFAULT_POOL_SIZE = 64; // Number of PDU buffers in total - const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps - + const static int DEFAULT_POOL_SIZE = 64; // Number of PDU buffers in total + const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps + typedef struct { - uint8_t ptr[MAX_PDU_LEN]; - uint32_t len; - uint32_t tstamp; + uint8_t ptr[MAX_PDU_LEN]; + uint32_t len; + uint32_t tstamp; + channel_t channel; #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED char debug_name[128]; #endif diff --git a/lib/include/srslte/common/threads.h b/lib/include/srslte/common/threads.h index e58f056b5..c6791ae7f 100644 --- a/lib/include/srslte/common/threads.h +++ b/lib/include/srslte/common/threads.h @@ -89,7 +89,7 @@ public: period_us = period_us_; start(priority); } - void stop() { + void stop_thread() { run_enable = false; wait_thread_finish(); } diff --git a/lib/include/srslte/common/timers.h b/lib/include/srslte/common/timers.h index a2d8dc15a..1b2bc1f83 100644 --- a/lib/include/srslte/common/timers.h +++ b/lib/include/srslte/common/timers.h @@ -64,7 +64,7 @@ public: return (counter < timeout) && running; } bool is_expired() { - return (timeout > 0) && (counter >= timeout || !running); + return (timeout > 0) && (counter >= timeout); } uint32_t get_timeout() { return timeout; diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index b1c0672d3..f0384a532 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -112,30 +112,34 @@ public: class nas_interface_rrc { public: + typedef enum { + BARRING_NONE = 0, + BARRING_MO_DATA, + BARRING_MO_SIGNALLING, + BARRING_MT, + BARRING_ALL + } barring_t; + virtual void set_barring(barring_t barring) = 0; + virtual void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) = 0; virtual bool is_attached() = 0; - virtual bool is_attaching() = 0; - virtual void notify_connection_setup() = 0; virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0; virtual uint32_t get_ul_count() = 0; - virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0; virtual bool get_k_asme(uint8_t *k_asme_, uint32_t n) = 0; - virtual bool plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0; - virtual void plmn_search_end() = 0; }; // NAS interface for UE class nas_interface_ue { public: - virtual void attach_request() = 0; - virtual void deattach_request() = 0; + virtual bool attach_request() = 0; + virtual bool deattach_request() = 0; }; // NAS interface for UE class nas_interface_gw { public: - virtual void attach_request() = 0; + virtual bool attach_request() = 0; }; // RRC interface for MAC @@ -159,8 +163,6 @@ class rrc_interface_phy public: virtual void in_sync() = 0; virtual void out_of_sync() = 0; - virtual void earfcn_end() = 0; - virtual void cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp = NAN) = 0; virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn = -1, int pci = -1) = 0; }; @@ -168,12 +170,23 @@ public: class rrc_interface_nas { public: + typedef struct { + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; + uint16_t tac; + } found_plmn_t; + + const static int MAX_FOUND_PLMNS = 16; + virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; virtual uint16_t get_mcc() = 0; virtual uint16_t get_mnc() = 0; virtual void enable_capabilities() = 0; - virtual void plmn_search() = 0; - virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request = false) = 0; + virtual int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) = 0; + virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0; + virtual bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, + srslte::byte_buffer_t *dedicatedInfoNAS) = 0; + virtual void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) = 0; + virtual bool is_connected() = 0; virtual std::string get_rb_name(uint32_t lcid) = 0; }; @@ -380,12 +393,7 @@ public: /* Indicate successfull decoding of PCH TB through PDSCH */ virtual void pch_decoded_ok(uint32_t len) = 0; - - /* Function called every start of a subframe (TTI). Warning, this function is called - * from a high priority thread and should terminate asap - */ - virtual void tti_clock(uint32_t tti) = 0; - + }; /* Interface RRC -> MAC shared between different RATs */ @@ -420,15 +428,14 @@ public: uint32_t prach_config_index; } mac_cfg_t; + virtual void clear_rntis() = 0; + /* Instructs the MAC to start receiving BCCH */ - virtual void bcch_start_rx() = 0; - virtual void bcch_stop_rx() = 0; virtual void bcch_start_rx(int si_window_start, int si_window_length) = 0; /* Instructs the MAC to start receiving PCCH */ virtual void pcch_start_rx() = 0; - virtual void pcch_stop_rx() = 0; - + /* RRC configures a logical channel */ virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0; @@ -487,9 +494,10 @@ typedef struct { uint32_t cfo_loop_pss_conv; uint32_t cfo_ref_mask; bool average_subframe_enabled; - int time_correct_period; + bool estimator_fil_auto; + float estimator_fil_stddev; + uint32_t estimator_fil_order; std::string sss_algorithm; - float estimator_fil_w; bool rssi_sensor_enabled; bool sic_pss_enabled; float rx_gain_offset; @@ -503,9 +511,7 @@ typedef struct { class phy_interface_mac_common { public: - /* Start synchronization with strongest cell in the current carrier frequency */ - virtual bool sync_status() = 0; - + /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ virtual void set_crnti(uint16_t rnti) = 0; @@ -581,15 +587,20 @@ public: virtual int meas_start(uint32_t earfcn, int pci = -1) = 0; virtual int meas_stop(uint32_t earfcn, int pci = -1) = 0; - /* Cell search and selection procedures */ - virtual void cell_search_start() = 0; - virtual void cell_search_next() = 0; - virtual void cell_select(uint32_t earfcn, srslte_cell_t cell) = 0; - virtual bool cell_handover(srslte_cell_t cell) = 0; + typedef struct { + enum {CELL_FOUND = 0, CELL_NOT_FOUND, ERROR} found; + enum {MORE_FREQS = 0, NO_MORE_FREQS} last_freq; + } cell_search_ret_t; - /* Is the PHY downlink synchronized? */ - virtual bool sync_status() = 0; - virtual void sync_reset() = 0; + typedef struct { + srslte_cell_t cell; + uint32_t earfcn; + } phy_cell_t; + + /* Cell search and selection procedures */ + virtual cell_search_ret_t cell_search(phy_cell_t *cell) = 0; + virtual bool cell_select(phy_cell_t *cell = NULL) = 0; + virtual bool cell_is_camping() = 0; /* Configure UL using parameters written with set_param() */ virtual void configure_ul_params(bool pregen_disabled = false) = 0; diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index a521d653e..653ee0075 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -74,6 +74,7 @@ typedef struct { float snr_vector[12000]; float pilot_power[12000]; #endif + bool smooth_filter_auto; uint32_t smooth_filter_len; float smooth_filter[SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN]; @@ -112,10 +113,10 @@ SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q); SRSLTE_API int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q, uint16_t mbsfn_area_id); + SRSLTE_API int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell); - SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len); @@ -123,6 +124,13 @@ SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w); +SRSLTE_API void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, + uint32_t order, + float std_dev); + +SRSLTE_API void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t* q, + bool enable); + SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q, srslte_chest_dl_noise_alg_t noise_estimation_alg); diff --git a/lib/include/srslte/phy/mimo/precoding.h b/lib/include/srslte/phy/mimo/precoding.h index d363231e2..5caf4f0ca 100644 --- a/lib/include/srslte/phy/mimo/precoding.h +++ b/lib/include/srslte/phy/mimo/precoding.h @@ -87,7 +87,7 @@ SRSLTE_API int srslte_predecoding_single(cf_t *y, SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, - float *csi, + float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_symbols, float scaling, @@ -102,7 +102,8 @@ SRSLTE_API int srslte_predecoding_diversity(cf_t *y, SRSLTE_API int srslte_predecoding_diversity_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_ports, int nof_symbols, @@ -113,7 +114,7 @@ SRSLTE_API void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo SRSLTE_API int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - float *csi, + float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_ports, int nof_layers, diff --git a/lib/include/srslte/phy/phch/sch.h b/lib/include/srslte/phy/phch/sch.h index 4ef0328e7..003e9b7df 100644 --- a/lib/include/srslte/phy/phch/sch.h +++ b/lib/include/srslte/phy/phch/sch.h @@ -64,7 +64,7 @@ typedef struct SRSLTE_API { uint8_t *parity_bits; void *e; uint8_t *temp_g_bits; - uint16_t *ul_interleaver; + uint32_t *ul_interleaver; srslte_uci_bit_t ack_ri_bits[12*288]; uint32_t nof_ri_ack_bits; diff --git a/lib/include/srslte/phy/utils/bit.h b/lib/include/srslte/phy/utils/bit.h index 29fca8e9e..8a4ff789b 100644 --- a/lib/include/srslte/phy/utils/bit.h +++ b/lib/include/srslte/phy/utils/bit.h @@ -70,6 +70,17 @@ SRSLTE_API void srslte_bit_copy(uint8_t *dst, uint32_t src_offset, uint32_t nof_bits); +SRSLTE_API void srslte_bit_interleave_i(uint8_t *input, + uint8_t *output, + uint32_t *interleaver, + uint32_t nof_bits); + +SRSLTE_API void srslte_bit_interleave_i_w_offset(uint8_t *input, + uint8_t *output, + uint32_t *interleaver, + uint32_t nof_bits, + uint32_t w_offset); + SRSLTE_API void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *interleaver, diff --git a/lib/include/srslte/phy/utils/mat.h b/lib/include/srslte/phy/utils/mat.h index a0f11abe3..8db0205f9 100644 --- a/lib/include/srslte/phy/utils/mat.h +++ b/lib/include/srslte/phy/utils/mat.h @@ -53,12 +53,17 @@ SRSLTE_API void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1, float noise_estimate, float norm); +SRSLTE_API void srslte_mat_2x2_mmse_csi_gen(cf_t y0, cf_t y1, + cf_t h00, cf_t h01, cf_t h10, cf_t h11, + cf_t *x0, cf_t *x1, float *csi0, float *csi1, + float noise_estimate, + float norm); + SRSLTE_API float srslte_mat_2x2_cn(cf_t h00, cf_t h01, cf_t h10, cf_t h11); - #ifdef LV_HAVE_SSE /* SSE implementation for complex reciprocal */ @@ -103,4 +108,114 @@ SRSLTE_API void srslte_mat_2x2_mmse_avx(__m256 y0, __m256 y1, #endif /* LV_HAVE_AVX */ -#endif // SRSLTE_MAT_H +#if SRSLTE_SIMD_CF_SIZE != 0 + +/* Generic SIMD implementation for 2x2 determinant */ +static inline simd_cf_t srslte_mat_2x2_det_simd(simd_cf_t a00, simd_cf_t a01, simd_cf_t a10, simd_cf_t a11) { + return srslte_simd_cf_sub(srslte_simd_cf_prod(a00, a11), srslte_simd_cf_prod(a01, a10)); +} + +/* Generic SIMD implementation for Zero Forcing (ZF) solver */ +static inline void srslte_mat_2x2_zf_csi_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + simd_f_t *csi0, + simd_f_t *csi1, + float norm) { + simd_cf_t det = srslte_mat_2x2_det_simd(h00, h01, h10, h11); + simd_cf_t detrec = srslte_simd_cf_mul(srslte_simd_cf_rcp(det), srslte_simd_f_set1(norm)); + + *x0 = srslte_simd_cf_prod(srslte_simd_cf_sub(srslte_simd_cf_prod(h11, y0), srslte_simd_cf_prod(h01, y1)), detrec); + *x1 = srslte_simd_cf_prod(srslte_simd_cf_sub(srslte_simd_cf_prod(h00, y1), srslte_simd_cf_prod(h10, y0)), detrec); + + *csi0 = srslte_simd_f_set1(1.0f); + *csi1 = srslte_simd_f_set1(1.0f); +} + +static inline void srslte_mat_2x2_zf_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + float norm) { + simd_f_t csi1, csi2; + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, x0, x1, &csi1, &csi2, norm); +} + +/* Generic SIMD implementation for Minimum Mean Squared Error (MMSE) solver */ +static inline void srslte_mat_2x2_mmse_csi_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + simd_f_t *csi0, + simd_f_t *csi1, + float noise_estimate, + float norm) { + simd_cf_t _noise_estimate; + simd_f_t _norm = srslte_simd_f_set1(norm); + + _noise_estimate.re = srslte_simd_f_set1(noise_estimate); + _noise_estimate.im = srslte_simd_f_zero(); + + /* 1. A = H' x H + No*/ + simd_cf_t a00 = + srslte_simd_cf_add(srslte_simd_cf_add(srslte_simd_cf_conjprod(h00, h00), srslte_simd_cf_conjprod(h10, h10)), + _noise_estimate); + simd_cf_t a01 = srslte_simd_cf_add(srslte_simd_cf_conjprod(h01, h00), srslte_simd_cf_conjprod(h11, h10)); + simd_cf_t a10 = srslte_simd_cf_add(srslte_simd_cf_conjprod(h00, h01), srslte_simd_cf_conjprod(h10, h11)); + simd_cf_t a11 = + srslte_simd_cf_add(srslte_simd_cf_add(srslte_simd_cf_conjprod(h01, h01), srslte_simd_cf_conjprod(h11, h11)), + _noise_estimate); + simd_cf_t a_det_rcp = srslte_simd_cf_rcp(srslte_mat_2x2_det_simd(a00, a01, a10, a11)); + + /* 2. B = inv(H' x H + No) = inv(A) */ + simd_cf_t _norm2 = srslte_simd_cf_mul(a_det_rcp, _norm); + simd_cf_t b00 = srslte_simd_cf_prod(a11, _norm2); + simd_cf_t b01 = srslte_simd_cf_prod(srslte_simd_cf_neg(a01), _norm2); + simd_cf_t b10 = srslte_simd_cf_prod(srslte_simd_cf_neg(a10), _norm2); + simd_cf_t b11 = srslte_simd_cf_prod(a00, _norm2); + + + /* 3. W = inv(H' x H + No) x H' = B x H' */ + simd_cf_t w00 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b00, h00), srslte_simd_cf_conjprod(b01, h01)); + simd_cf_t w01 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b00, h10), srslte_simd_cf_conjprod(b01, h11)); + simd_cf_t w10 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b10, h00), srslte_simd_cf_conjprod(b11, h01)); + simd_cf_t w11 = srslte_simd_cf_add(srslte_simd_cf_conjprod(b10, h10), srslte_simd_cf_conjprod(b11, h11)); + + /* 4. X = W x Y */ + *x0 = srslte_simd_cf_add(srslte_simd_cf_prod(y0, w00), srslte_simd_cf_prod(y1, w01)); + *x1 = srslte_simd_cf_add(srslte_simd_cf_prod(y0, w10), srslte_simd_cf_prod(y1, w11)); + + /* 5. Extract CSI */ + *csi0 = srslte_simd_f_rcp(srslte_simd_cf_re(b00)); + *csi1 = srslte_simd_f_rcp(srslte_simd_cf_re(b11)); +} + +static inline void srslte_mat_2x2_mmse_simd(simd_cf_t y0, + simd_cf_t y1, + simd_cf_t h00, + simd_cf_t h01, + simd_cf_t h10, + simd_cf_t h11, + simd_cf_t *x0, + simd_cf_t *x1, + float noise_estimate, + float norm) { + simd_f_t csi0, csi1; + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, x0, x1, &csi0, &csi1, noise_estimate, norm); +} + +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ +#endif /* SRSLTE_MAT_H */ diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index f6d7a0a44..e9cb4da30 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -197,7 +197,7 @@ static inline simd_f_t srslte_simd_f_loadu(const 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 @@ -233,7 +233,7 @@ static inline void srslte_simd_f_storeu(float *ptr, simd_f_t simdreg) { #ifdef LV_HAVE_AVX512 _mm512_storeu_ps(ptr, simdreg); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 _mm256_storeu_ps(ptr, simdreg); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE @@ -360,7 +360,7 @@ 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 @@ -376,9 +376,9 @@ static inline simd_f_t srslte_simd_f_zero (void) { return _mm512_setzero_ps(); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - return _mm256_setzero_ps(); + 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 @@ -401,7 +401,7 @@ static inline simd_f_t srslte_simd_f_swap(simd_f_t a) { #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 /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -443,7 +443,7 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #ifdef LV_HAVE_AVX512 return _mm512_sqrt_ps(a); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 return _mm256_sqrt_ps(a); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE @@ -458,7 +458,43 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { float32x4_t zeros = vmovq_n_f32(0); /* Zero vector */ uint32x4_t mask = vceqq_f32(a, zeros); /* Zero vector mask */ return vbslq_f32(mask, zeros, result); /* Force zero results and return */ -#endif /* HAVE_NEON */ +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_neg(simd_f_t a) { +#ifdef LV_HAVE_AVX512 + return _mm512_xor_ps(_mm512_set1_ps(-0.0f), a); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_xor_ps(_mm256_set1_ps(-0.0f), a); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_xor_ps(_mm_set1_ps(-0.0f), a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vnegq_f32(a); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_neg_mask(simd_f_t a, simd_f_t mask) { +#ifdef LV_HAVE_AVX512 + return _mm512_xor_ps(mask, a); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_xor_ps(mask, a); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_xor_ps(mask, a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return (float32x4_t) veorq_s32((int32x4_t) a, (int32x4_t) mask); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -470,12 +506,11 @@ 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; +typedef float32x4x2_t simd_cf_t; #else typedef struct { simd_f_t re; simd_f_t im; - } simd_cf_t; #endif @@ -667,8 +702,8 @@ static inline void srslte_simd_cf_store(float *re, float *im, simd_cf_t simdreg) _mm512_store_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - _mm256_store_ps((float *) re, simdreg.re); - _mm256_store_ps((float *) im, simdreg.im); + _mm256_store_ps(re, simdreg.re); + _mm256_store_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_SSE _mm_store_ps((float *) re, simdreg.re); @@ -689,8 +724,8 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg _mm512_storeu_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - _mm256_storeu_ps((float *) re, simdreg.re); - _mm256_storeu_ps((float *) im, simdreg.im); + _mm256_storeu_ps(re, simdreg.re); + _mm256_storeu_ps(im, simdreg.im); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_SSE _mm_storeu_ps((float *) re, simdreg.re); @@ -833,8 +868,32 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { return ret; } +static inline simd_cf_t srslte_simd_cf_sub (simd_cf_t a, simd_cf_t b) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_sub_ps(a.re, b.re); + ret.im = _mm512_sub_ps(a.im, b.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_sub_ps(a.re, b.re); + ret.im = _mm256_sub_ps(a.im, b.im); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + ret.re = _mm_sub_ps(a.re, b.re); + ret.im = _mm_sub_ps(a.im, b.im); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vsubq_f32(a.val[0],b.val[0]); + ret.val[1] = vsubq_f32(a.val[1],b.val[1]); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { - simd_cf_t ret; + simd_cf_t ret; #ifdef LV_HAVE_AVX512 ret.re = _mm512_mul_ps(a.re, b); ret.im = _mm512_mul_ps(a.im, b); @@ -855,7 +914,7 @@ static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ - return ret; + return ret; } static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { @@ -902,6 +961,59 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { return ret; } +static inline simd_cf_t srslte_simd_cf_neg (simd_cf_t a) { + simd_cf_t ret; +#if LV_HAVE_NEON + ret.val[0] = srslte_simd_f_neg(a.val[0]); + ret.val[1] = srslte_simd_f_neg(a.val[1]); +#else /* LV_HAVE_NEON */ + ret.re = srslte_simd_f_neg(a.re); + ret.im = srslte_simd_f_neg(a.im); +#endif /* LV_HAVE_NEON */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_neg_mask (simd_cf_t a, simd_f_t mask) { + simd_cf_t ret; +#ifndef LV_HAVE_AVX512 +#ifdef LV_HAVE_AVX2 + mask = _mm256_permutevar8x32_ps(mask, _mm256_setr_epi32(0,4,1,5,2,6,3,7)); +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +#if LV_HAVE_NEON + ret.val[0] = srslte_simd_f_neg_mask(a.val[0], mask); + ret.val[1] = srslte_simd_f_neg_mask(a.val[1], mask); +#else /* LV_HAVE_NEON */ + ret.re = srslte_simd_f_neg_mask(a.re, mask); + ret.im = srslte_simd_f_neg_mask(a.im, mask); +#endif /* LV_HAVE_NEON */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_conj (simd_cf_t a) { + simd_cf_t ret; +#if LV_HAVE_NEON + ret.val[0] = a.val[0]; + ret.val[1] = srslte_simd_f_neg(a.val[1]); +#else /* LV_HAVE_NEON */ + ret.re = a.re; + ret.im = srslte_simd_f_neg(a.im); +#endif /* LV_HAVE_NEON */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_mulj (simd_cf_t a) { + simd_cf_t ret; +#if LV_HAVE_NEON + ret.val[0] = srslte_simd_f_neg(a.val[1]); + ret.val[1] = a.val[0]; +#else /* LV_HAVE_NEON */ + ret.re = srslte_simd_f_neg(a.im); + ret.im = a.re; +#endif /* LV_HAVE_NEON */ + return ret; +} + static inline simd_cf_t srslte_simd_cf_zero (void) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 @@ -1057,7 +1169,7 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s 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{ @@ -1115,7 +1227,7 @@ static inline simd_s_t srslte_simd_s_loadu(const int16_t *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_si512(ptr); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 1fcbe4235..d6742fb3c 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -99,6 +99,7 @@ SRSLTE_API void srslte_vec_convert_fi(const float *x, const float scale, int16_t SRSLTE_API void srslte_vec_convert_if(const int16_t *x, const float scale, float *z, const uint32_t len); SRSLTE_API void srslte_vec_lut_sss(const short *x, const unsigned short *lut, short *y, const uint32_t len); +SRSLTE_API void srslte_vec_lut_sis(const short *x, const unsigned int *lut, short *y, const uint32_t len); /* vector product (element-wise) */ SRSLTE_API void srslte_vec_prod_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 26775777b..5137bd13b 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -34,150 +34,152 @@ #define SRSLTE_RADIO_H typedef struct { - float tx_corr_dc_gain; - float tx_corr_dc_phase; - float tx_corr_iq_i; - float tx_corr_iq_q; - float rx_corr_dc_gain; - float rx_corr_dc_phase; - float rx_corr_iq_i; - float rx_corr_iq_q; -}rf_cal_t; - + float tx_corr_dc_gain; + float tx_corr_dc_phase; + float tx_corr_iq_i; + float tx_corr_iq_q; + float rx_corr_dc_gain; + float rx_corr_dc_phase; + float rx_corr_iq_i; + float rx_corr_iq_q; +} rf_cal_t; namespace srslte { - + /* Interface to the RF frontend. */ - class radio - { - public: - radio() : tr_local_time(1024*10), tr_usrp_time(1024*10), tr_tx_time(1024*10), tr_is_eob(1024*10) { - bzero(&rf_device, sizeof(srslte_rf_t)); - bzero(&end_of_burst_time, sizeof(srslte_timestamp_t)); - bzero(zeros, burst_preamble_max_samples*sizeof(cf_t)); - - burst_preamble_sec = 0; - is_start_of_burst = false; - burst_preamble_samples = 0; - burst_preamble_time_rounded = 0; - - cur_tx_srate = 0; - tx_adv_sec = 0; - tx_adv_nsamples = 0; - tx_adv_auto = false; - tx_adv_negative = false; - tx_freq = 0; - rx_freq = 0; - trace_enabled = false; - tti = 0; - agc_enabled = false; - radio_is_streaming = false; - is_initialized = false; - }; - - bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); - void stop(); - void reset(); - bool start_agc(bool tx_gain_same_rx); - - void set_burst_preamble(double preamble_us); - void set_tx_adv(int nsamples); - void set_tx_adv_neg(bool tx_adv_is_neg); - - void set_manual_calibration(rf_cal_t *calibration); - - void get_time(srslte_timestamp_t *now); - bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); - bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); - void tx_end(); - bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time); - bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); +class radio { + public: + radio() : tr_local_time(1024 * 10), tr_usrp_time(1024 * 10), tr_tx_time(1024 * 10), tr_is_eob(1024 * 10) { + bzero(&rf_device, sizeof(srslte_rf_t)); + bzero(&end_of_burst_time, sizeof(srslte_timestamp_t)); + bzero(zeros, burst_preamble_max_samples * sizeof(cf_t)); - void set_tx_gain(float gain); - void set_rx_gain(float gain); - void set_tx_rx_gain_offset(float offset); - double set_rx_gain_th(float gain); + burst_preamble_sec = 0; + is_start_of_burst = false; + burst_preamble_samples = 0; + burst_preamble_time_rounded = 0; - void set_freq_offset(double freq); - void set_tx_freq(double freq); - void set_rx_freq(double freq); + cur_tx_srate = 0; + tx_adv_sec = 0; + tx_adv_nsamples = 0; + tx_adv_auto = false; + tx_adv_negative = false; + tx_freq = 0; + rx_freq = 0; + trace_enabled = false; + tti = 0; + agc_enabled = false; + radio_is_streaming = false; + is_initialized = false; + continuous_tx = false; + }; - double get_freq_offset(); - double get_tx_freq(); - double get_rx_freq(); + bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); + void stop(); + void reset(); + bool start_agc(bool tx_gain_same_rx); - void set_master_clock_rate(double rate); - void set_tx_srate(double srate); - void set_rx_srate(double srate); + void set_burst_preamble(double preamble_us); + void set_tx_adv(int nsamples); + void set_tx_adv_neg(bool tx_adv_is_neg); - float get_tx_gain(); - float get_rx_gain(); - - float get_max_tx_power(); - float set_tx_power(float power); - float get_rssi(); - bool has_rssi(); - - void start_trace(); - void write_trace(std::string filename); + void set_manual_calibration(rf_cal_t *calibration); - void set_tti(uint32_t tti); + bool is_continuous_tx(); + void set_continuous_tx(bool enable); - bool is_first_of_burst(); + void get_time(srslte_timestamp_t *now); + bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); + void tx_end(); + bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time); + bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); - bool is_init(); + void set_tx_gain(float gain); + void set_rx_gain(float gain); + void set_tx_rx_gain_offset(float offset); + double set_rx_gain_th(float gain); - void register_error_handler(srslte_rf_error_handler_t h); - - protected: - - void save_trace(uint32_t is_eob, srslte_timestamp_t *usrp_time); - - srslte_rf_t rf_device; - - - const static uint32_t burst_preamble_max_samples = 30720000; // 30.72 MHz is maximum frequency - double burst_preamble_sec;// Start of burst preamble time (off->on RF transition time) - srslte_timestamp_t end_of_burst_time; - bool is_start_of_burst; - uint32_t burst_preamble_samples; - double burst_preamble_time_rounded; // preamble time rounded to sample time - cf_t zeros[burst_preamble_max_samples]; - double cur_tx_srate; + void set_freq_offset(double freq); + void set_tx_freq(double freq); + void set_rx_freq(double freq); - double tx_adv_sec; // Transmission time advance to compensate for antenna->timestamp delay - int tx_adv_nsamples; // Transmision time advance in number of samples - - // Define default values for known radios - bool tx_adv_auto; - bool tx_adv_negative; - const static double uhd_default_burst_preamble_sec = 600*1e-6; - const static double uhd_default_tx_adv_samples = 98; - const static double uhd_default_tx_adv_offset_sec = 4*1e-6; - - const static double blade_default_burst_preamble_sec = 0.0; - const static double blade_default_tx_adv_samples = 27; - const static double blade_default_tx_adv_offset_sec = 1e-6; + double get_freq_offset(); + double get_tx_freq(); + double get_rx_freq(); - double tx_freq, rx_freq, freq_offset; - - trace tr_local_time; - trace tr_usrp_time; - trace tr_tx_time; - trace tr_is_eob; - bool trace_enabled; - uint32_t tti; - bool agc_enabled; + void set_master_clock_rate(double rate); + void set_tx_srate(double srate); + void set_rx_srate(double srate); - bool is_initialized = true;; - bool radio_is_streaming; + float get_tx_gain(); + float get_rx_gain(); - uint32_t saved_nof_channels; - char saved_args[128]; - char saved_devname[128]; + float get_max_tx_power(); + float set_tx_power(float power); + float get_rssi(); + bool has_rssi(); - }; + void start_trace(); + void write_trace(std::string filename); + + void set_tti(uint32_t tti); + + bool is_first_of_burst(); + + bool is_init(); + + void register_error_handler(srslte_rf_error_handler_t h); + + protected: + + void save_trace(uint32_t is_eob, srslte_timestamp_t *usrp_time); + + srslte_rf_t rf_device; + + const static uint32_t burst_preamble_max_samples = 30720000; // 30.72 MHz is maximum frequency + double burst_preamble_sec;// Start of burst preamble time (off->on RF transition time) + srslte_timestamp_t end_of_burst_time; + bool is_start_of_burst; + uint32_t burst_preamble_samples; + double burst_preamble_time_rounded; // preamble time rounded to sample time + cf_t zeros[burst_preamble_max_samples]; + double cur_tx_srate; + + double tx_adv_sec; // Transmission time advance to compensate for antenna->timestamp delay + int tx_adv_nsamples; // Transmision time advance in number of samples + + // Define default values for known radios + bool tx_adv_auto; + bool tx_adv_negative; + const static double uhd_default_burst_preamble_sec = 600 * 1e-6; + const static double uhd_default_tx_adv_samples = 98; + const static double uhd_default_tx_adv_offset_sec = 4 * 1e-6; + + const static double blade_default_burst_preamble_sec = 0.0; + const static double blade_default_tx_adv_samples = 27; + const static double blade_default_tx_adv_offset_sec = 1e-6; + + double tx_freq, rx_freq, freq_offset; + + trace tr_local_time; + trace tr_usrp_time; + trace tr_tx_time; + trace tr_is_eob; + bool trace_enabled; + uint32_t tti; + bool agc_enabled; + + bool continuous_tx; + bool is_initialized; + bool radio_is_streaming; + + uint32_t saved_nof_channels; + char saved_args[128]; + char saved_devname[128]; + +}; } #endif // SRSLTE_RADIO_H diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index e8a5d9561..de51ed1de 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -32,7 +32,6 @@ #include "srslte/common/common.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/security.h" -#include "srslte/common/msg_queue.h" #include "srslte/common/threads.h" diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index c4d57b9bb..05472e0e8 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -31,7 +31,6 @@ #include "srslte/common/log.h" #include "srslte/common/common.h" #include "srslte/interfaces/ue_interfaces.h" -#include "srslte/common/msg_queue.h" #include "srslte/upper/rlc_entity.h" #include "srslte/upper/rlc_metrics.h" #include "srslte/upper/rlc_common.h" diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 6d9dedcdc..0425e8a35 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -2225,14 +2225,14 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_network_name_ie(LIBLTE_MME_NETWORK_NAME_STRUCT uint32 i; uint32 bit_offset; uint32 byte_offset; - const char *char_str = net_name->name.c_str(); + const char *char_str = net_name->name; if(net_name != NULL && ie_ptr != NULL) { bit_offset = 0; byte_offset = 2; - for(i=0; iname.size(); i++) + for(i=0; iname = ""; - while(byte_offset < N_bytes) + str_cnt = 0; + + while(byte_offset < N_bytes && str_cnt < LIBLTE_STRING_LEN) { switch(bit_offset) { @@ -2389,7 +2391,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8 (tmp_char >= 0x61 && tmp_char <= 0x7A)) { - net_name->name += tmp_char; + if (str_cnt < LIBLTE_STRING_LEN) { + net_name->name[str_cnt] = tmp_char; + str_cnt++; + } } } @@ -2412,10 +2417,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8 (tmp_char >= 0x61 && tmp_char <= 0x7A)) { - net_name->name += tmp_char; + if (str_cnt < LIBLTE_STRING_LEN) { + net_name->name[str_cnt] = tmp_char; + str_cnt++; + } } } + if (str_cnt < LIBLTE_STRING_LEN) { + net_name->name[str_cnt] = '\0'; + str_cnt++; + } + *ie_ptr += byte_offset + 1; err = LIBLTE_SUCCESS; @@ -3765,12 +3778,12 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_N if(apn != NULL && ie_ptr != NULL) { - apn_str = apn->apn.c_str(); - (*ie_ptr)[0] = apn->apn.length()+1; + apn_str = apn->apn; + (*ie_ptr)[0] = strnlen(apn->apn, LIBLTE_STRING_LEN)+1; len_idx = 0; apn_idx = 0; label_len = 0; - while(apn->apn.length() > apn_idx) + while(strnlen(apn->apn, LIBLTE_STRING_LEN) > apn_idx) { (*ie_ptr)[1+apn_idx+1] = (uint8)apn_str[apn_idx]; apn_idx++; @@ -3785,7 +3798,7 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_N } } (*ie_ptr)[1+len_idx] = label_len; - *ie_ptr += apn->apn.length() + 2; + *ie_ptr += strnlen(apn->apn, LIBLTE_STRING_LEN) + 2; err = LIBLTE_SUCCESS; } @@ -3799,26 +3812,31 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 uint32 i; uint32 ie_idx; uint32 label_len; + uint32 str_cnt; if(ie_ptr != NULL && apn != NULL) { - apn->apn.clear(); ie_idx = 0; - while(ie_idx < (*ie_ptr)[0]) + str_cnt = 0; + while(ie_idx < (*ie_ptr)[0] && str_cnt < LIBLTE_STRING_LEN) { label_len = (*ie_ptr)[1+ie_idx]; - for(i=0; iapn += (char)((*ie_ptr)[1+ie_idx+i+1]); + apn->apn[str_cnt] = (char)((*ie_ptr)[1+ie_idx+i+1]); + str_cnt++; } ie_idx += label_len + 1; - if(ie_idx < (*ie_ptr)[0]) + if(ie_idx < (*ie_ptr)[0] && str_cnt < LIBLTE_STRING_LEN) { - apn->apn += '.'; + apn->apn[str_cnt] = '.'; + str_cnt++; } } - apn->apn += "\0"; + if (str_cnt < LIBLTE_STRING_LEN) { + apn->apn[str_cnt] = '\0'; + } *ie_ptr += (*ie_ptr)[0] + 1; err = LIBLTE_SUCCESS; diff --git a/lib/src/asn1/liblte_rrc.cc b/lib/src/asn1/liblte_rrc.cc index 74beb46cf..8e489cd9f 100644 --- a/lib/src/asn1/liblte_rrc.cc +++ b/lib/src/asn1/liblte_rrc.cc @@ -380,7 +380,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_c_rnti_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_cdma2000, +LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000, uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -412,7 +412,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_SIMPLE_BYTE_ return(err); } LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, - LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_cdma2000) + LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; @@ -452,7 +452,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_nas, +LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_BYTE_MSG_STRUCT *ded_info_nas, uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -484,7 +484,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_SIMPLE_BYTE_MSG_S return(err); } LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_nas_ie(uint8 **ie_ptr, - LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_nas) + LIBLTE_BYTE_MSG_STRUCT *ded_info_nas) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; @@ -2715,8 +2715,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_eutra_ie(LIBLTE_RRC_REPORT_CONFI liblte_value_2_bits(rep_cnfg_eutra->trigger_type, ie_ptr, 1); if(LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT == rep_cnfg_eutra->trigger_type) { + // Event ID choice extension indicator + liblte_value_2_bits(0, ie_ptr, 1); // Choice with extension - unlikely to be >63 choices + // Event ID - // FIXME: Handle extension properly liblte_value_2_bits(rep_cnfg_eutra->event.event_id, ie_ptr, 3); if(LIBLTE_RRC_EVENT_ID_EUTRA_A1 == rep_cnfg_eutra->event.event_id) { diff --git a/lib/src/asn1/liblte_s1ap.cc b/lib/src/asn1/liblte_s1ap.cc index e6a8fe575..ea0b1ec92 100644 --- a/lib/src/asn1/liblte_s1ap.cc +++ b/lib/src/asn1/liblte_s1ap.cc @@ -12586,7 +12586,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabinformationlistitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -14074,7 +14074,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rablist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -15610,7 +15610,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransferlist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_bearers_subjecttostatustransfer_item(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -18814,7 +18814,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionlistres( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -18900,7 +18900,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionlistresack( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19110,7 +19110,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsubjecttodataforwardinglist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabdataforwardingitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19196,7 +19196,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplisthoreq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemhoreq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19282,7 +19282,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmittedlist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabadmitteditem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19368,7 +19368,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddllist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitcheddlitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19454,7 +19454,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedullist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitchedulitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19540,7 +19540,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplistbearersureq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitembearersureq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19626,7 +19626,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuplistbearersures( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitembearersures(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19712,7 +19712,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifiedlistbearermodreq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19798,7 +19798,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifylistbearermodres( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabmodifyitembearermodres(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19884,7 +19884,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaselistbearerrelcomp( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -19970,7 +19970,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplistctxtsureq( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -20056,7 +20056,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuplistctxtsures( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitemctxtsures(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -20142,7 +20142,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tailist( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_taiitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -20228,7 +20228,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetuplisthoreqack( uint32_t i; for(i=0;ilen;i++) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24400,7 +24400,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourceenb_totargetenb_transparentcontainer_ex // ProtocolIE - MobilityInformation if(msg->MobilityInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mobilityinformation(&msg->MobilityInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24500,7 +24500,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlist( uint8_t *tmp_ptr; // ProtocolIE - E_RABInformationListItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabinformationlistitem(&msg->E_RABInformationListItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24602,7 +24602,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedeutrancellinformation_ext( // ProtocolIE - Time_UE_StayedInCell_EnhancedGranularity if(msg->Time_UE_StayedInCell_EnhancedGranularity_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_time_ue_stayedincell_enhancedgranularity(&msg->Time_UE_StayedInCell_EnhancedGranularity, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24621,7 +24621,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedeutrancellinformation_ext( // ProtocolIE - HO_Cause if(msg->HO_Cause_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->HO_Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24731,7 +24731,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_soninformationreply_ext( // ProtocolIE - Time_Synchronization_Info if(msg->Time_Synchronization_Info_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timesynchronizationinfo(&msg->Time_Synchronization_Info, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24838,7 +24838,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext( // ProtocolIE - ULCOUNTValueExtended if(msg->ULCOUNTValueExtended_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_countvalueextended(&msg->ULCOUNTValueExtended, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24857,7 +24857,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext( // ProtocolIE - DLCOUNTValueExtended if(msg->DLCOUNTValueExtended_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_countvalueextended(&msg->DLCOUNTValueExtended, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24876,7 +24876,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext( // ProtocolIE - ReceiveStatusOfULPDCPSDUsExtended if(msg->ReceiveStatusOfULPDCPSDUsExtended_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_receivestatusofulpdcpsdusextended(&msg->ReceiveStatusOfULPDCPSDUsExtended, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -24990,7 +24990,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabitem(&msg->E_RABItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25090,7 +25090,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdt_configuration_ext( // ProtocolIE - SignallingBasedMDTPLMNList if(msg->SignallingBasedMDTPLMNList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdtplmnlist(&msg->SignallingBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25193,7 +25193,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_x2tnlconfigurationinfo_ext( // ProtocolIE - eNBX2ExtendedTransportLayerAddresses if(msg->eNBX2ExtendedTransportLayerAddresses_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enbx2exttlas(&msg->eNBX2ExtendedTransportLayerAddresses, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25293,7 +25293,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_item( uint8_t *tmp_ptr; // ProtocolIE - Bearers_SubjectToStatusTransfer_Item - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_bearers_subjecttostatustransfer_item(&msg->Bearers_SubjectToStatusTransfer_Item, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25399,7 +25399,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - M3Configuration if(msg->M3Configuration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_m3configuration(&msg->M3Configuration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25418,7 +25418,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - M4Configuration if(msg->M4Configuration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_m4configuration(&msg->M4Configuration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25437,7 +25437,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - M5Configuration if(msg->M5Configuration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_m5configuration(&msg->M5Configuration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25456,7 +25456,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext( // ProtocolIE - MDT_Location_Info if(msg->MDT_Location_Info_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdt_location_info(&msg->MDT_Location_Info, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25577,7 +25577,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_sonconfigurationtransfer_ext( // ProtocolIE - x2TNLConfigurationInfo if(msg->x2TNLConfigurationInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_x2tnlconfigurationinfo(&msg->x2TNLConfigurationInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25679,7 +25679,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_traceactivation_ext( // ProtocolIE - MDTConfiguration if(msg->MDTConfiguration_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdt_configuration(&msg->MDTConfiguration, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25795,7 +25795,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25812,7 +25812,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25829,7 +25829,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - HandoverType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25846,7 +25846,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25863,7 +25863,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( *ptr += tmp_msg.N_bits; // ProtocolIE - TargetID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_targetid(&msg->TargetID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25881,7 +25881,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - Direct_Forwarding_Path_Availability if(msg->Direct_Forwarding_Path_Availability_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_direct_forwarding_path_availability(&msg->Direct_Forwarding_Path_Availability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25900,7 +25900,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - SRVCCHOIndication if(msg->SRVCCHOIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_srvcchoindication(&msg->SRVCCHOIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25918,7 +25918,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( } // ProtocolIE - Source_ToTarget_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25936,7 +25936,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - Source_ToTarget_TransparentContainer_Secondary if(msg->Source_ToTarget_TransparentContainer_Secondary_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer_Secondary, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25955,7 +25955,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - MSClassmark2 if(msg->MSClassmark2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_msclassmark2(&msg->MSClassmark2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25974,7 +25974,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - MSClassmark3 if(msg->MSClassmark3_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_msclassmark3(&msg->MSClassmark3, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -25993,7 +25993,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26012,7 +26012,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26031,7 +26031,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired( // ProtocolIE - PS_ServiceNotAvailable if(msg->PS_ServiceNotAvailable_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ps_servicenotavailable(&msg->PS_ServiceNotAvailable, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26278,7 +26278,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26295,7 +26295,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26312,7 +26312,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26330,7 +26330,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26448,7 +26448,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq_ext( // ProtocolIE - Data_Forwarding_Not_Possible if(msg->Data_Forwarding_Not_Possible_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_data_forwarding_not_possible(&msg->Data_Forwarding_Not_Possible, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26686,7 +26686,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26703,7 +26703,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26721,7 +26721,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26835,7 +26835,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26852,7 +26852,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26869,7 +26869,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26886,7 +26886,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26904,7 +26904,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( // ProtocolIE - Tunnel_Information_for_BBF if(msg->Tunnel_Information_for_BBF_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -26923,7 +26923,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27188,7 +27188,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27205,7 +27205,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27222,7 +27222,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27240,7 +27240,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27355,7 +27355,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27372,7 +27372,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27389,7 +27389,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27498,7 +27498,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27515,7 +27515,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27533,7 +27533,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27648,7 +27648,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureqext( // ProtocolIE - Correlation_ID if(msg->Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27667,7 +27667,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureqext( // ProtocolIE - SIPTO_Correlation_ID if(msg->SIPTO_Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->SIPTO_Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -27845,7 +27845,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifyitembearermodreqext( // ProtocolIE - TransportInformation if(msg->TransportInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportinformation(&msg->TransportInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28017,7 +28017,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28034,7 +28034,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28052,7 +28052,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28070,7 +28070,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( } // ProtocolIE - E_RABToBeReleasedList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABToBeReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28088,7 +28088,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand( // ProtocolIE - NAS_PDU if(msg->NAS_PDU_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28280,7 +28280,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28297,7 +28297,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28314,7 +28314,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABReleasedList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28332,7 +28332,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication( // ProtocolIE - UserLocationInformation if(msg->UserLocationInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28452,7 +28452,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureqext( // ProtocolIE - Correlation_ID if(msg->Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28471,7 +28471,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureqext( // ProtocolIE - SIPTO_Correlation_ID if(msg->SIPTO_Correlation_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_correlation_id(&msg->SIPTO_Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28648,7 +28648,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28665,7 +28665,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28682,7 +28682,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28700,7 +28700,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28885,7 +28885,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28902,7 +28902,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28919,7 +28919,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -28937,7 +28937,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest( // ProtocolIE - GWContextReleaseIndication if(msg->GWContextReleaseIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gwcontextreleaseindication(&msg->GWContextReleaseIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29052,7 +29052,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecommand( uint8_t *tmp_ptr; // ProtocolIE - UE_S1AP_IDs - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_s1ap_ids(&msg->UE_S1AP_IDs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29069,7 +29069,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecommand( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29175,7 +29175,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29192,7 +29192,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29210,7 +29210,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29229,7 +29229,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete( // ProtocolIE - UserLocationInformation if(msg->UserLocationInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29362,7 +29362,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29379,7 +29379,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29397,7 +29397,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - SecurityKey if(msg->SecurityKey_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitykey(&msg->SecurityKey, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29416,7 +29416,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - SubscriberProfileIDforRFP if(msg->SubscriberProfileIDforRFP_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29435,7 +29435,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29454,7 +29454,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - CSFallbackIndicator if(msg->CSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csfallbackindicator(&msg->CSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29473,7 +29473,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - UESecurityCapabilities if(msg->UESecurityCapabilities_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29492,7 +29492,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29511,7 +29511,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - RegisteredLAI if(msg->RegisteredLAI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lai(&msg->RegisteredLAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29530,7 +29530,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest( // ProtocolIE - AdditionalCSFallbackIndicator if(msg->AdditionalCSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_additionalcsfallbackindicator(&msg->AdditionalCSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29690,7 +29690,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29707,7 +29707,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29725,7 +29725,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29837,7 +29837,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29854,7 +29854,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29871,7 +29871,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -29889,7 +29889,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30006,7 +30006,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30023,7 +30023,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30041,7 +30041,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest( // ProtocolIE - UERadioCapability if(msg->UERadioCapability_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30153,7 +30153,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30170,7 +30170,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30187,7 +30187,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - VoiceSupportMatchIndicator - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_voicesupportmatchindicator(&msg->VoiceSupportMatchIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30205,7 +30205,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30324,7 +30324,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30341,7 +30341,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30358,7 +30358,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30376,7 +30376,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( // ProtocolIE - HandoverRestrictionList if(msg->HandoverRestrictionList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30395,7 +30395,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport( // ProtocolIE - SubscriberProfileIDforRFP if(msg->SubscriberProfileIDforRFP_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30537,7 +30537,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( uint8_t *tmp_ptr; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30554,7 +30554,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30571,7 +30571,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30588,7 +30588,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30605,7 +30605,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( *ptr += tmp_msg.N_bits; // ProtocolIE - RRC_Establishment_Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_rrc_establishment_cause(&msg->RRC_Establishment_Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30623,7 +30623,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - S_TMSI if(msg->S_TMSI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_s_tmsi(&msg->S_TMSI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30642,7 +30642,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30661,7 +30661,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - GUMMEI_ID if(msg->GUMMEI_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30680,7 +30680,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30699,7 +30699,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - GW_TransportLayerAddress if(msg->GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30718,7 +30718,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - RelayNode_Indicator if(msg->RelayNode_Indicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_relaynode_indicator(&msg->RelayNode_Indicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30737,7 +30737,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - GUMMEIType if(msg->GUMMEIType_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummeitype(&msg->GUMMEIType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30756,7 +30756,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - Tunnel_Information_for_BBF if(msg->Tunnel_Information_for_BBF_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30775,7 +30775,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - SIPTO_L_GW_TransportLayerAddress if(msg->SIPTO_L_GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->SIPTO_L_GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30794,7 +30794,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -30988,7 +30988,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31005,7 +31005,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31022,7 +31022,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31039,7 +31039,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31056,7 +31056,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31074,7 +31074,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( // ProtocolIE - GW_TransportLayerAddress if(msg->GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31093,7 +31093,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( // ProtocolIE - SIPTO_L_GW_TransportLayerAddress if(msg->SIPTO_L_GW_TransportLayerAddress_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->SIPTO_L_GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31112,7 +31112,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31251,7 +31251,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31268,7 +31268,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31285,7 +31285,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( *ptr += tmp_msg.N_bits; // ProtocolIE - NAS_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31302,7 +31302,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31414,7 +31414,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitem( uint8_t *tmp_ptr; // ProtocolIE - UE_associatedLogicalS1_ConnectionItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&msg->UE_associatedLogicalS1_ConnectionItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31511,7 +31511,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitemres( uint8_t *tmp_ptr; // ProtocolIE - UE_associatedLogicalS1_ConnectionItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&msg->UE_associatedLogicalS1_ConnectionItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31617,7 +31617,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - MME_UE_S1AP_ID if(msg->MME_UE_S1AP_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31636,7 +31636,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - eNB_UE_S1AP_ID if(msg->eNB_UE_S1AP_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31655,7 +31655,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - Cause if(msg->Cause_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31674,7 +31674,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31799,7 +31799,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( uint8_t *tmp_ptr; // ProtocolIE - Global_ENB_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_global_enb_id(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31817,7 +31817,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( // ProtocolIE - eNBname if(msg->eNBname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31835,7 +31835,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( } // ProtocolIE - SupportedTAs - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_supportedtas(&msg->SupportedTAs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31852,7 +31852,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - DefaultPagingDRX - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingdrx(&msg->DefaultPagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31870,7 +31870,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest( // ProtocolIE - CSG_IdList if(msg->CSG_IdList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -31999,7 +31999,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( // ProtocolIE - MMEname if(msg->MMEname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mmename(&msg->MMEname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32017,7 +32017,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( } // ProtocolIE - ServedGUMMEIs - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_servedgummeis(&msg->ServedGUMMEIs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32034,7 +32034,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - RelativeMMECapacity - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_relativemmecapacity(&msg->RelativeMMECapacity, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32052,7 +32052,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( // ProtocolIE - MMERelaySupportIndicator if(msg->MMERelaySupportIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mmerelaysupportindicator(&msg->MMERelaySupportIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32071,7 +32071,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32199,7 +32199,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32217,7 +32217,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure( // ProtocolIE - TimeToWait if(msg->TimeToWait_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32236,7 +32236,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32357,7 +32357,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - eNBname if(msg->eNBname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32376,7 +32376,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - SupportedTAs if(msg->SupportedTAs_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_supportedtas(&msg->SupportedTAs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32395,7 +32395,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - CSG_IdList if(msg->CSG_IdList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32414,7 +32414,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate( // ProtocolIE - DefaultPagingDRX if(msg->DefaultPagingDRX_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingdrx(&msg->DefaultPagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32538,7 +32538,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdateacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32642,7 +32642,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32660,7 +32660,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure( // ProtocolIE - TimeToWait if(msg->TimeToWait_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32679,7 +32679,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32798,7 +32798,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate( // ProtocolIE - MMEname if(msg->MMEname_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mmename(&msg->MMEname, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32817,7 +32817,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate( // ProtocolIE - ServedGUMMEIs if(msg->ServedGUMMEIs_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_servedgummeis(&msg->ServedGUMMEIs, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32836,7 +32836,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate( // ProtocolIE - RelativeMMECapacity if(msg->RelativeMMECapacity_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_relativemmecapacity(&msg->RelativeMMECapacity, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -32953,7 +32953,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdateacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33057,7 +33057,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33075,7 +33075,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure( // ProtocolIE - TimeToWait if(msg->TimeToWait_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33094,7 +33094,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33214,7 +33214,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33231,7 +33231,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33248,7 +33248,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - cdma2000RATType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000rattype(&msg->cdma2000RATType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33265,7 +33265,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - cdma2000SectorID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000sectorid(&msg->cdma2000SectorID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33283,7 +33283,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - cdma2000HORequiredIndication if(msg->cdma2000HORequiredIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000horequiredindication(&msg->cdma2000HORequiredIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33302,7 +33302,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - cdma2000OneXSRVCCInfo if(msg->cdma2000OneXSRVCCInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000onexsrvccinfo(&msg->cdma2000OneXSRVCCInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33321,7 +33321,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - cdma2000OneXRAND if(msg->cdma2000OneXRAND_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000onexrand(&msg->cdma2000OneXRAND, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33339,7 +33339,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( } // ProtocolIE - cdma2000PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000pdu(&msg->cdma2000PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33357,7 +33357,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling( // ProtocolIE - EUTRANRoundTripDelayEstimationInfo if(msg->EUTRANRoundTripDelayEstimationInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutranroundtripdelayestimationinfo(&msg->EUTRANRoundTripDelayEstimationInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33503,7 +33503,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33520,7 +33520,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33537,7 +33537,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication( *ptr += tmp_msg.N_bits; // ProtocolIE - UERadioCapability - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33644,7 +33644,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33661,7 +33661,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33678,7 +33678,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_StatusTransfer_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_statustransfer_transparentcontainer(&msg->eNB_StatusTransfer_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33785,7 +33785,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33802,7 +33802,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33819,7 +33819,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_StatusTransfer_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_statustransfer_transparentcontainer(&msg->eNB_StatusTransfer_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33926,7 +33926,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33943,7 +33943,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -33960,7 +33960,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart( *ptr += tmp_msg.N_bits; // ProtocolIE - TraceActivation - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34067,7 +34067,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34084,7 +34084,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34101,7 +34101,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - E_UTRAN_Trace_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34118,7 +34118,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34230,7 +34230,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34247,7 +34247,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34264,7 +34264,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace( *ptr += tmp_msg.N_bits; // ProtocolIE - E_UTRAN_Trace_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34373,7 +34373,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34390,7 +34390,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34407,7 +34407,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - E_UTRAN_Trace_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34424,7 +34424,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34441,7 +34441,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( *ptr += tmp_msg.N_bits; // ProtocolIE - TraceCollectionEntityIPAddress - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_transportlayeraddress(&msg->TraceCollectionEntityIPAddress, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34459,7 +34459,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace( // ProtocolIE - PrivacyIndicator if(msg->PrivacyIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_privacyindicator(&msg->PrivacyIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34584,7 +34584,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34601,7 +34601,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34618,7 +34618,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol( *ptr += tmp_msg.N_bits; // ProtocolIE - RequestType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34725,7 +34725,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34742,7 +34742,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34759,7 +34759,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34866,7 +34866,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34883,7 +34883,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34900,7 +34900,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34917,7 +34917,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -34934,7 +34934,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport( *ptr += tmp_msg.N_bits; // ProtocolIE - RequestType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35055,7 +35055,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart( uint8_t *tmp_ptr; // ProtocolIE - OverloadResponse - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_overloadresponse(&msg->OverloadResponse, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35073,7 +35073,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart( // ProtocolIE - GUMMEIList if(msg->GUMMEIList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummeilist(&msg->GUMMEIList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35092,7 +35092,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart( // ProtocolIE - TrafficLoadReductionIndication if(msg->TrafficLoadReductionIndication_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_trafficloadreductionindication(&msg->TrafficLoadReductionIndication, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35207,7 +35207,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstop( // ProtocolIE - GUMMEIList if(msg->GUMMEIList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummeilist(&msg->GUMMEIList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35321,7 +35321,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35338,7 +35338,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35356,7 +35356,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningAreaList if(msg->WarningAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningarealist(&msg->WarningAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35374,7 +35374,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( } // ProtocolIE - RepetitionPeriod - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_repetitionperiod(&msg->RepetitionPeriod, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35392,7 +35392,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - ExtendedRepetitionPeriod if(msg->ExtendedRepetitionPeriod_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_extendedrepetitionperiod(&msg->ExtendedRepetitionPeriod, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35410,7 +35410,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( } // ProtocolIE - NumberofBroadcastRequest - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_numberofbroadcastrequest(&msg->NumberofBroadcastRequest, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35428,7 +35428,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningType if(msg->WarningType_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningtype(&msg->WarningType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35447,7 +35447,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningSecurityInfo if(msg->WarningSecurityInfo_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningsecurityinfo(&msg->WarningSecurityInfo, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35466,7 +35466,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - DataCodingScheme if(msg->DataCodingScheme_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_datacodingscheme(&msg->DataCodingScheme, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35485,7 +35485,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - WarningMessageContents if(msg->WarningMessageContents_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningmessagecontents(&msg->WarningMessageContents, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35504,7 +35504,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest( // ProtocolIE - ConcurrentWarningMessageIndicator if(msg->ConcurrentWarningMessageIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_concurrentwarningmessageindicator(&msg->ConcurrentWarningMessageIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35670,7 +35670,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35687,7 +35687,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35705,7 +35705,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( // ProtocolIE - BroadcastCompletedAreaList if(msg->BroadcastCompletedAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_broadcastcompletedarealist(&msg->BroadcastCompletedAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35724,7 +35724,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35841,7 +35841,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmedirectinformationtransfer( uint8_t *tmp_ptr; // ProtocolIE - Inter_SystemInformationTransferTypeMDT - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_inter_systeminformationtransfertype(&msg->Inter_SystemInformationTransferTypeMDT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -35941,7 +35941,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationtransfer( // ProtocolIE - SONConfigurationTransferECT if(msg->SONConfigurationTransferECT_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_sonconfigurationtransfer(&msg->SONConfigurationTransferECT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36044,7 +36044,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationtransfer( // ProtocolIE - SONConfigurationTransferMCT if(msg->SONConfigurationTransferMCT_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_sonconfigurationtransfer(&msg->SONConfigurationTransferMCT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36216,7 +36216,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36233,7 +36233,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36251,7 +36251,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( // ProtocolIE - WarningAreaList if(msg->WarningAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_warningarealist(&msg->WarningAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36270,7 +36270,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest( // ProtocolIE - KillAllWarningMessages if(msg->KillAllWarningMessages_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_killallwarningmessages(&msg->KillAllWarningMessages, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36391,7 +36391,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( uint8_t *tmp_ptr; // ProtocolIE - MessageIdentifier - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36408,7 +36408,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - SerialNumber - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36426,7 +36426,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( // ProtocolIE - BroadcastCancelledAreaList if(msg->BroadcastCancelledAreaList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_broadcastcancelledarealist(&msg->BroadcastCancelledAreaList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36445,7 +36445,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36564,7 +36564,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( uint8_t *tmp_ptr; // ProtocolIE - ECGIListForRestart - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ecgilistforrestart(&msg->ECGIListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36581,7 +36581,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( *ptr += tmp_msg.N_bits; // ProtocolIE - Global_ENB_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_global_enb_id(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36598,7 +36598,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( *ptr += tmp_msg.N_bits; // ProtocolIE - TAIListForRestart - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tailistforrestart(&msg->TAIListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36616,7 +36616,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication( // ProtocolIE - EmergencyAreaIDListForRestart if(msg->EmergencyAreaIDListForRestart_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_emergencyareaidlistforrestart(&msg->EmergencyAreaIDListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36731,7 +36731,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36748,7 +36748,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36765,7 +36765,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36782,7 +36782,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36894,7 +36894,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36911,7 +36911,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36928,7 +36928,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -36945,7 +36945,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37057,7 +37057,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknonueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37074,7 +37074,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknonueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37176,7 +37176,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknonueassociatedlppatransport( uint8_t *tmp_ptr; // ProtocolIE - Routing_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37193,7 +37193,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknonueassociatedlppatransport( *ptr += tmp_msg.N_bits; // ProtocolIE - LPPa_PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37295,7 +37295,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbdirectinformationtransfer( uint8_t *tmp_ptr; // ProtocolIE - Inter_SystemInformationTransferTypeEDT - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_inter_systeminformationtransfertype(&msg->Inter_SystemInformationTransferTypeEDT, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37392,7 +37392,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabdataforwardingitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABDataForwardingItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabdataforwardingitem(&msg->E_RABDataForwardingItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37489,7 +37489,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSetupItemHOReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemhoreq(&msg->E_RABToBeSetupItemHOReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37586,7 +37586,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmitteditem( uint8_t *tmp_ptr; // ProtocolIE - E_RABAdmittedItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabadmitteditem(&msg->E_RABAdmittedItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37683,7 +37683,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack( uint8_t *tmp_ptr; // ProtocolIE - E_RABFailedtoSetupItemHOReqAck - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(&msg->E_RABFailedtoSetupItemHOReqAck, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37780,7 +37780,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddlitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSwitchedDLItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitcheddlitem(&msg->E_RABToBeSwitchedDLItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37877,7 +37877,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedulitem( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSwitchedULItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitchedulitem(&msg->E_RABToBeSwitchedULItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -37974,7 +37974,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSetupItemBearerSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitembearersureq(&msg->E_RABToBeSetupItemBearerSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38071,7 +38071,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitembearersures( uint8_t *tmp_ptr; // ProtocolIE - E_RABSetupItemBearerSURes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitembearersures(&msg->E_RABSetupItemBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38168,7 +38168,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifieditembearermodreq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeModifiedItemBearerModReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(&msg->E_RABToBeModifiedItemBearerModReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38265,7 +38265,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyitembearermodres( uint8_t *tmp_ptr; // ProtocolIE - E_RABModifyItemBearerModRes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabmodifyitembearermodres(&msg->E_RABModifyItemBearerModRes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38362,7 +38362,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseitembearerrelcomp( uint8_t *tmp_ptr; // ProtocolIE - E_RABReleaseItemBearerRelComp - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(&msg->E_RABReleaseItemBearerRelComp, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38459,7 +38459,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureq( uint8_t *tmp_ptr; // ProtocolIE - E_RABToBeSetupItemCtxtSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(&msg->E_RABToBeSetupItemCtxtSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38556,7 +38556,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitemctxtsures( uint8_t *tmp_ptr; // ProtocolIE - E_RABSetupItemCtxtSURes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetupitemctxtsures(&msg->E_RABSetupItemCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38653,7 +38653,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_taiitem( uint8_t *tmp_ptr; // ProtocolIE - TAIItem - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_taiitem(&msg->TAIItem, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38755,7 +38755,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_resetacknowledge( // ProtocolIE - UE_associatedLogicalS1_ConnectionListResAck if(msg->UE_associatedLogicalS1_ConnectionListResAck_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ue_associatedlogicals1_connectionlistresack(&msg->UE_associatedLogicalS1_ConnectionListResAck, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38774,7 +38774,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_resetacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38881,7 +38881,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_reset( uint8_t *tmp_ptr; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -38898,7 +38898,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_reset( *ptr += tmp_msg.N_bits; // ProtocolIE - ResetType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_resettype(&msg->ResetType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39004,7 +39004,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39021,7 +39021,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39039,7 +39039,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( // ProtocolIE - E_RABSubjecttoDataForwardingList if(msg->E_RABSubjecttoDataForwardingList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(&msg->E_RABSubjecttoDataForwardingList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39058,7 +39058,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( // ProtocolIE - cdma2000HOStatus if(msg->cdma2000HOStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000hostatus(&msg->cdma2000HOStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39076,7 +39076,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( } // ProtocolIE - cdma2000RATType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000rattype(&msg->cdma2000RATType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39093,7 +39093,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling( *ptr += tmp_msg.N_bits; // ProtocolIE - cdma2000PDU - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cdma2000pdu(&msg->cdma2000PDU, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39229,7 +39229,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39246,7 +39246,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39263,7 +39263,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( *ptr += tmp_msg.N_bits; // ProtocolIE - HandoverType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39281,7 +39281,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - NASSecurityParametersfromE_UTRAN if(msg->NASSecurityParametersfromE_UTRAN_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nassecurityparametersfrome_utran(&msg->NASSecurityParametersfromE_UTRAN, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39300,7 +39300,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - E_RABSubjecttoDataForwardingList if(msg->E_RABSubjecttoDataForwardingList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(&msg->E_RABSubjecttoDataForwardingList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39319,7 +39319,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - E_RABtoReleaseListHOCmd if(msg->E_RABtoReleaseListHOCmd_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABtoReleaseListHOCmd, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39337,7 +39337,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( } // ProtocolIE - Target_ToSource_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39355,7 +39355,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - Target_ToSource_TransparentContainer_Secondary if(msg->Target_ToSource_TransparentContainer_Secondary_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer_Secondary, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39374,7 +39374,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39543,7 +39543,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39560,7 +39560,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - HandoverType - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39577,7 +39577,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - Cause - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39594,7 +39594,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - uEaggregateMaximumBitrate - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39611,7 +39611,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABToBeSetupListHOReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetuplisthoreq(&msg->E_RABToBeSetupListHOReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39628,7 +39628,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - Source_ToTarget_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39645,7 +39645,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - UESecurityCapabilities - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39663,7 +39663,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - HandoverRestrictionList if(msg->HandoverRestrictionList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39682,7 +39682,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - TraceActivation if(msg->TraceActivation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39701,7 +39701,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - RequestType if(msg->RequestType_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39720,7 +39720,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - SRVCCOperationPossible if(msg->SRVCCOperationPossible_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_srvccoperationpossible(&msg->SRVCCOperationPossible, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39738,7 +39738,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( } // ProtocolIE - SecurityContext - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitycontext(&msg->SecurityContext, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39756,7 +39756,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - NASSecurityParameterstoE_UTRAN if(msg->NASSecurityParameterstoE_UTRAN_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_nassecurityparameterstoe_utran(&msg->NASSecurityParameterstoE_UTRAN, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39775,7 +39775,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39794,7 +39794,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39813,7 +39813,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - GUMMEI_ID if(msg->GUMMEI_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39832,7 +39832,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - MME_UE_S1AP_ID_2 if(msg->MME_UE_S1AP_ID_2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39851,7 +39851,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - ManagementBasedMDTAllowed if(msg->ManagementBasedMDTAllowed_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_managementbasedmdtallowed(&msg->ManagementBasedMDTAllowed, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -39870,7 +39870,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest( // ProtocolIE - ManagementBasedMDTPLMNList if(msg->ManagementBasedMDTPLMNList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdtplmnlist(&msg->ManagementBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40091,7 +40091,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( uint8_t *tmp_ptr; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40108,7 +40108,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABToBeSwitchedDLList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitcheddllist(&msg->E_RABToBeSwitchedDLList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40125,7 +40125,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SourceMME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->SourceMME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40142,7 +40142,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - EUTRAN_CGI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40159,7 +40159,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - TAI - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40176,7 +40176,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - UESecurityCapabilities - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40194,7 +40194,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40213,7 +40213,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40232,7 +40232,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - SourceMME_GUMMEI if(msg->SourceMME_GUMMEI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->SourceMME_GUMMEI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40251,7 +40251,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40270,7 +40270,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - Tunnel_Information_for_BBF if(msg->Tunnel_Information_for_BBF_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40289,7 +40289,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest( // ProtocolIE - LHN_ID if(msg->LHN_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40466,7 +40466,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40483,7 +40483,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40501,7 +40501,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40520,7 +40520,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - E_RABToBeSwitchedULList if(msg->E_RABToBeSwitchedULList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobeswitchedullist(&msg->E_RABToBeSwitchedULList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40539,7 +40539,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - E_RABToBeReleasedList if(msg->E_RABToBeReleasedList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABToBeReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40557,7 +40557,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( } // ProtocolIE - SecurityContext - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitycontext(&msg->SecurityContext, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40575,7 +40575,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40594,7 +40594,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - MME_UE_S1AP_ID_2 if(msg->MME_UE_S1AP_ID_2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40613,7 +40613,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40765,7 +40765,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40782,7 +40782,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40800,7 +40800,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40818,7 +40818,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest( } // ProtocolIE - E_RABToBeSetupListBearerSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetuplistbearersureq(&msg->E_RABToBeSetupListBearerSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40938,7 +40938,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40955,7 +40955,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40973,7 +40973,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( // ProtocolIE - E_RABSetupListBearerSURes if(msg->E_RABSetupListBearerSURes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetuplistbearersures(&msg->E_RABSetupListBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -40992,7 +40992,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( // ProtocolIE - E_RABFailedToSetupListBearerSURes if(msg->E_RABFailedToSetupListBearerSURes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToSetupListBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41011,7 +41011,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41137,7 +41137,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41154,7 +41154,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41172,7 +41172,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( // ProtocolIE - uEaggregateMaximumBitrate if(msg->uEaggregateMaximumBitrate_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41190,7 +41190,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest( } // ProtocolIE - E_RABToBeModifiedListBearerModReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobemodifiedlistbearermodreq(&msg->E_RABToBeModifiedListBearerModReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41310,7 +41310,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41327,7 +41327,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41345,7 +41345,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( // ProtocolIE - E_RABModifyListBearerModRes if(msg->E_RABModifyListBearerModRes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabmodifylistbearermodres(&msg->E_RABModifyListBearerModRes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41364,7 +41364,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( // ProtocolIE - E_RABFailedToModifyList if(msg->E_RABFailedToModifyList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToModifyList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41383,7 +41383,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41515,7 +41515,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41532,7 +41532,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41550,7 +41550,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - E_RABReleaseListBearerRelComp if(msg->E_RABReleaseListBearerRelComp_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabreleaselistbearerrelcomp(&msg->E_RABReleaseListBearerRelComp, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41569,7 +41569,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - E_RABFailedToReleaseList if(msg->E_RABFailedToReleaseList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToReleaseList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41588,7 +41588,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41607,7 +41607,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse( // ProtocolIE - UserLocationInformation if(msg->UserLocationInformation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41764,7 +41764,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41781,7 +41781,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41798,7 +41798,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - uEaggregateMaximumBitrate - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41815,7 +41815,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABToBeSetupListCtxtSUReq - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabtobesetuplistctxtsureq(&msg->E_RABToBeSetupListCtxtSUReq, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41832,7 +41832,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - UESecurityCapabilities - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41849,7 +41849,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( *ptr += tmp_msg.N_bits; // ProtocolIE - SecurityKey - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_securitykey(&msg->SecurityKey, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41867,7 +41867,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - TraceActivation if(msg->TraceActivation_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41886,7 +41886,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - HandoverRestrictionList if(msg->HandoverRestrictionList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41905,7 +41905,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - UERadioCapability if(msg->UERadioCapability_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41924,7 +41924,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - SubscriberProfileIDforRFP if(msg->SubscriberProfileIDforRFP_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41943,7 +41943,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - CSFallbackIndicator if(msg->CSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csfallbackindicator(&msg->CSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41962,7 +41962,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - SRVCCOperationPossible if(msg->SRVCCOperationPossible_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_srvccoperationpossible(&msg->SRVCCOperationPossible, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -41981,7 +41981,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - CSGMembershipStatus if(msg->CSGMembershipStatus_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42000,7 +42000,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - RegisteredLAI if(msg->RegisteredLAI_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_lai(&msg->RegisteredLAI, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42019,7 +42019,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - GUMMEI_ID if(msg->GUMMEI_ID_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42038,7 +42038,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - MME_UE_S1AP_ID_2 if(msg->MME_UE_S1AP_ID_2_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42057,7 +42057,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - ManagementBasedMDTAllowed if(msg->ManagementBasedMDTAllowed_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_managementbasedmdtallowed(&msg->ManagementBasedMDTAllowed, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42076,7 +42076,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - ManagementBasedMDTPLMNList if(msg->ManagementBasedMDTPLMNList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mdtplmnlist(&msg->ManagementBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42095,7 +42095,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest( // ProtocolIE - AdditionalCSFallbackIndicator if(msg->AdditionalCSFallbackIndicator_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_additionalcsfallbackindicator(&msg->AdditionalCSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42312,7 +42312,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42329,7 +42329,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42346,7 +42346,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABSetupListCtxtSURes - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabsetuplistctxtsures(&msg->E_RABSetupListCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42364,7 +42364,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( // ProtocolIE - E_RABFailedToSetupListCtxtSURes if(msg->E_RABFailedToSetupListCtxtSURes_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToSetupListCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42383,7 +42383,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42511,7 +42511,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( uint8_t *tmp_ptr; // ProtocolIE - UEIdentityIndexValue - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_ueidentityindexvalue(&msg->UEIdentityIndexValue, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42528,7 +42528,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( *ptr += tmp_msg.N_bits; // ProtocolIE - UEPagingID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_uepagingid(&msg->UEPagingID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42546,7 +42546,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( // ProtocolIE - pagingDRX if(msg->pagingDRX_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingdrx(&msg->pagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42564,7 +42564,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( } // ProtocolIE - CNDomain - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cndomain(&msg->CNDomain, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42581,7 +42581,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( *ptr += tmp_msg.N_bits; // ProtocolIE - TAIList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_tailist(&msg->TAIList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42599,7 +42599,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( // ProtocolIE - CSG_IdList if(msg->CSG_IdList_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42618,7 +42618,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging( // ProtocolIE - PagingPriority if(msg->PagingPriority_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_pagingpriority(&msg->PagingPriority, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42760,7 +42760,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( uint8_t *tmp_ptr; // ProtocolIE - MME_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42777,7 +42777,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - eNB_UE_S1AP_ID - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42794,7 +42794,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( *ptr += tmp_msg.N_bits; // ProtocolIE - E_RABAdmittedList - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabadmittedlist(&msg->E_RABAdmittedList, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42812,7 +42812,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - E_RABFailedToSetupListHOReqAck if(msg->E_RABFailedToSetupListHOReqAck_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_e_rabfailedtosetuplisthoreqack(&msg->E_RABFailedToSetupListHOReqAck, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42830,7 +42830,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( } // ProtocolIE - Target_ToSource_TransparentContainer - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42848,7 +42848,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - CSG_Id if(msg->CSG_Id_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42867,7 +42867,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - CriticalityDiagnostics if(msg->CriticalityDiagnostics_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -42886,7 +42886,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge( // ProtocolIE - CellAccessMode if(msg->CellAccessMode_present) { - tmp_msg.reset(); + tmp_ptr = tmp_msg.msg; if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) { return LIBLTE_ERROR_ENCODE_FAIL; @@ -44006,7 +44006,7 @@ LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1ap_pdu( } liblte_align_up_zero(ptr, 8); - bit_msg.N_bits += (*ptr - bit_msg.msg); + bit_msg.N_bits = (*ptr - bit_msg.msg); liblte_pack(&bit_msg, msg); err = LIBLTE_SUCCESS; diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index a86a36f1e..9602e202a 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -136,7 +136,7 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level, } void log_filter::console(const char * message, ...) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -147,7 +147,7 @@ void log_filter::console(const char * message, ...) { void log_filter::error(const char * message, ...) { if (level >= LOG_LEVEL_ERROR) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -158,7 +158,7 @@ void log_filter::error(const char * message, ...) { } void log_filter::warning(const char * message, ...) { if (level >= LOG_LEVEL_WARNING) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -169,7 +169,7 @@ void log_filter::warning(const char * message, ...) { } void log_filter::info(const char * message, ...) { if (level >= LOG_LEVEL_INFO) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -180,7 +180,7 @@ void log_filter::info(const char * message, ...) { } void log_filter::debug(const char * message, ...) { if (level >= LOG_LEVEL_DEBUG) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -192,7 +192,7 @@ void log_filter::debug(const char * message, ...) { void log_filter::error_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_ERROR) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -203,7 +203,7 @@ void log_filter::error_hex(const uint8_t *hex, int size, const char * message, . } void log_filter::warning_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_WARNING) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -214,7 +214,7 @@ void log_filter::warning_hex(const uint8_t *hex, int size, const char * message, } void log_filter::info_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_INFO) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) @@ -225,7 +225,7 @@ void log_filter::info_hex(const uint8_t *hex, int size, const char * message, .. } void log_filter::debug_hex(const uint8_t *hex, int size, const char * message, ...) { if (level >= LOG_LEVEL_DEBUG) { - char *args_msg; + char *args_msg = NULL; va_list args; va_start(args, message); if(vasprintf(&args_msg, message, args) > 0) diff --git a/lib/src/common/pdu_queue.cc b/lib/src/common/pdu_queue.cc index 061433033..9b5e83c7b 100644 --- a/lib/src/common/pdu_queue.cc +++ b/lib/src/common/pdu_queue.cc @@ -74,12 +74,13 @@ void pdu_queue::deallocate(uint8_t* pdu) * This function enqueues the packet and returns quicly because ACK * deadline is important here. */ -void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp) +void pdu_queue::push(uint8_t *ptr, uint32_t len, channel_t channel, uint32_t tstamp) { if (ptr) { pdu_t *pdu = (pdu_t*) ptr; pdu->len = len; pdu->tstamp = tstamp; + pdu->channel = channel; pdu_q.push(pdu); } else { log_h->warning("Error pushing pdu: ptr is empty\n"); @@ -88,15 +89,17 @@ void pdu_queue::push(uint8_t *ptr, uint32_t len, uint32_t tstamp) bool pdu_queue::process_pdus() { - bool have_data = false; - uint32_t cnt = 0; - pdu_t *pdu; + bool have_data = false; + uint32_t cnt = 0; + pdu_t *pdu; while(pdu_q.try_pop(&pdu)) { if (callback) { - callback->process_pdu(pdu->ptr, pdu->len, pdu->tstamp); + callback->process_pdu(pdu->ptr, pdu->len, pdu->channel, pdu->tstamp); } - if (!pool.deallocate(pdu)) { - log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n"); + if (pdu->channel == DCH) { + if (!pool.deallocate(pdu)) { + log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n"); + } } cnt++; have_data = true; diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index e719b22c0..238cd1a18 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -155,6 +155,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) q->rsrp_neighbour = false; + q->smooth_filter_auto = false; q->smooth_filter_len = 3; srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); @@ -263,41 +264,66 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell) /* Uses the difference between the averaged and non-averaged pilot estimates */ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslte_sf_t ch_mode) { - int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + const float weight = 1.0f; + float sum_power = 0.0f; + uint32_t count = 0; + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + uint32_t nsymbols = + (ch_mode == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols() : srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nref = npilots / nsymbols; + uint32_t fidx = srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); - if (q->average_subframe) { - if (ch_mode == SRSLTE_SF_MBSFN) { - nref /= 4; - } else { - nref /= 2; - } + cf_t *input2d[nsymbols + 2]; + cf_t *tmp_noise = q->tmp_noise; + + for (int i = 0; i < nsymbols; i++) { + input2d[i + 1] = &q->pilot_estimates[i * nref]; } - /* Substract noisy pilot estimates */ - srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); - -#ifdef FREQ_SEL_SNR - /* Compute frequency-selective SNR */ - srslte_vec_abs_square_cf(q->tmp_noise, q->snr_vector, nref); - srslte_vec_abs_square_cf(q->pilot_estimates, q->pilot_power, nref); - srslte_vec_div_fff(q->pilot_power, q->snr_vector, q->snr_vector, nref); - - srslte_vec_fprint_f(stdout, q->snr_vector, nref); -#endif - - /* Compute average power. Normalized for filter len 3 using matlab */ - float norm = 1; - if (q->average_subframe) { - norm = 32; + input2d[0] = &q->tmp_noise[0]; + if (nsymbols > 3) { + srslte_vec_sc_prod_cfc(input2d[2], 2.0f, input2d[0], nref); + srslte_vec_sub_ccc(input2d[0], input2d[4], input2d[0], nref); } else { - if (q->smooth_filter_len == 3) { - float a = q->smooth_filter[0]; - float norm3 = 6.143*a*a+0.04859*a-0.002774; - norm /= norm3; - } + srslte_vec_sc_prod_cfc(input2d[2], 1.0f, input2d[0], nref); } - float power = norm*srslte_vec_avg_power_cf(q->tmp_noise, nref); - return power; + + input2d[nsymbols + 1] = &q->tmp_noise[nref]; + if (nsymbols > 3) { + srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 2.0f, input2d[nsymbols + 1], nref); + srslte_vec_sub_ccc(input2d[nsymbols + 1], input2d[nsymbols - 3], input2d[nsymbols + 1], nref); + } else { + srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 1.0f, input2d[nsymbols + 1], nref); + } + + for (int i = 1; i < nsymbols + 1; i++) { + uint32_t offset = ((fidx < 3) ^ (i & 1)) ? 0 : 1; + srslte_vec_sc_prod_cfc(input2d[i], weight, tmp_noise, nref); + + srslte_vec_sum_ccc(&input2d[i - 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); + srslte_vec_sum_ccc(&input2d[i - 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); + if (offset) { + tmp_noise[0] += 2.0f * input2d[i - 1][0] - input2d[i - 1][1]; + } else { + tmp_noise[nref - 1] += 2.0f * input2d[i - 1][nref - 2] - input2d[i - 1][nref - 1]; + } + + srslte_vec_sum_ccc(&input2d[i + 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); + srslte_vec_sum_ccc(&input2d[i + 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); + if (offset) { + tmp_noise[0] += 2.0f * input2d[i + 1][0] - input2d[i + 1][1]; + } else { + tmp_noise[nref - 1] += 2.0f * input2d[i + 1][nref - 2] - input2d[i + 1][nref - 1]; + } + + srslte_vec_sc_prod_cfc(tmp_noise, 1.0f / (weight + 4.0f), tmp_noise, nref); + + srslte_vec_sub_ccc(input2d[i], tmp_noise, tmp_noise, nref); + sum_power = srslte_vec_avg_power_cf(tmp_noise, nref); + count++; + } + + return sum_power / (float) count * sqrtf(weight + 4.0f); } static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce) @@ -443,6 +469,53 @@ void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w) q->smooth_filter[1] = 1-2*w; } +void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, uint32_t order, float std_dev) +{ + const uint32_t filterlen = order + 1; + const int center = (filterlen - 1) / 2; + float *filter = q->smooth_filter; + float norm_p = 0.0f; + + if (filterlen) { + + for (int i = 0; i < filterlen; i++) { + filter[i] = expf(-powf(i - center, 2) / (2.0f * powf(std_dev, 2))); + norm_p += powf(filter[i], 2); + } + + const float norm = srslte_vec_acc_ff(filter, filterlen); + + srslte_vec_sc_prod_fff(filter, 1.0f / norm, filter, filterlen); + q->smooth_filter_len = filterlen; + } +} + +void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t *q, bool enable) { + q->smooth_filter_auto = enable; +} + +uint32_t srslte_chest_dl_interleave_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *tmp, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { + uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; + + if (srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0) < 3) { + srslte_vec_interleave(input, &input[nref], tmp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[l * nref], &input[(l + 1) * nref], tmp, nref); + } + } else { + srslte_vec_interleave(&input[nref], input, tmp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[(l + 1) * nref], &input[l * nref], tmp, nref); + } + } + + nref *= 2; + srslte_vec_sc_prod_cfc(tmp, 2.0f / nsymbols, output, nref); + + return nref; +} + static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; @@ -523,7 +596,16 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui q->cfo = chest_estimate_cfo(q); } + /* Estimate noise */ + if (q->noise_alg == SRSLTE_NOISE_ALG_REFS) { + q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); + } + if (ce != NULL) { + if (q->smooth_filter_auto) { + srslte_chest_dl_set_smooth_filter_gauss(q, 4, q->noise_estimate[rxant_id][port_id] * 200.0f); + } + /* Smooth estimates (if applicable) and interpolate */ if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) { interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode); @@ -533,13 +615,11 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } /* Estimate noise power */ - if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) { - q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); - } else if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { + if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce); } - } else { + } else if (q->noise_alg != SRSLTE_NOISE_ALG_REFS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input); } diff --git a/lib/src/phy/mimo/layermap.c b/lib/src/phy/mimo/layermap.c index a5bfc8b92..6de30fca7 100644 --- a/lib/src/phy/mimo/layermap.c +++ b/lib/src/phy/mimo/layermap.c @@ -54,7 +54,7 @@ int srslte_layermap_multiplex(cf_t *d[SRSLTE_MAX_CODEWORDS], cf_t *x[SRSLTE_MAX_ int nof_symbols[SRSLTE_MAX_CODEWORDS]) { if (nof_cw == nof_layers) { for (int i = 0; i < nof_cw; i++) { - srs_vec_cf_cpy(x[i], d[i], (uint32_t) nof_symbols[0]); + srs_vec_cf_cpy(d[i], x[i], (uint32_t) nof_symbols[0]); } return nof_symbols[0]; } else if (nof_cw == 1) { diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index f8faeda75..dbf34ab90 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -283,13 +283,13 @@ int srslte_predecoding_single_csi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ for (; i < nof_symbols; i++) { cf_t r = 0; float hh = 0; - float _scaling = 1.0f / scaling; + float norm = 1.0f / scaling; for (int p = 0; p < nof_rxant; p++) { r += y[p][i] * conj(h[p][i]); hh += (__real__ h[p][i] * __real__ h[p][i]) + (__imag__ h[p][i] * __imag__ h[p][i]); } csi[i] = hh + noise_estimate; - x[i] = r * _scaling / csi[i]; + x[i] = r * norm / csi[i]; } return nof_symbols; } @@ -327,10 +327,10 @@ int srslte_predecoding_single(cf_t *y_, cf_t *h_, cf_t *x, float *csi, int nof_s } /* ZF/MMSE SISO equalizer x=y(h'h+no)^(-1)h' (ZF if n0=0.0)*/ -int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, float *csi, +int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { - if (csi) { - return srslte_predecoding_single_csi(y, h, x, csi, nof_rxant, nof_symbols, scaling, noise_estimate); + if (csi && csi[0]) { + return srslte_predecoding_single_csi(y, h, x, csi[0], nof_rxant, nof_symbols, scaling, noise_estimate); } #ifdef LV_HAVE_AVX @@ -566,18 +566,123 @@ int srslte_predecoding_diversity(cf_t *y_, cf_t *h_[SRSLTE_MAX_PORTS], cf_t *x[S #endif } -int srslte_predecoding_diversity_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_symbols, float scaling) -{ -#ifdef LV_HAVE_SSE - if (nof_symbols > 32 && nof_ports == 2) { - return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols, scaling); +int srslte_predecoding_diversity_csi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, int nof_ports, int nof_symbols, float scaling) { + int i; + if (nof_ports == 2) { + cf_t h00, h01, h10, h11, r0, r1; + + for (i = 0; i < nof_symbols / 2; i++) { + float hh = 0; + cf_t x0 = 0; + cf_t x1 = 0; + for (int p=0;p 32 && nof_ports == 2) { + return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols, scaling); + } else { + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); + } #else - return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); -#endif + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); +#endif + } } int srslte_precoding_mimo_2x2_gen(cf_t W[2][2], cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], @@ -614,102 +719,78 @@ int srslte_precoding_mimo_2x2_gen(cf_t W[2][2], cf_t *y[SRSLTE_MAX_PORTS], cf_t return SRSLTE_SUCCESS; } -// AVX implementation of ZF 2x2 CCD equalizer -#ifdef LV_HAVE_AVX - -int srslte_predecoding_ccd_2x2_zf_avx(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, - float scaling) { +static int srslte_predecoding_ccd_2x2_zf_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_symbols, + float scaling) { uint32_t i = 0; + float norm = 2.0f / scaling; - __m256 mask0 = _mm256_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f); - __m256 mask1 = _mm256_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f); - - for (i = 0; i < nof_symbols - 3; i += 4) { - /* Load channel */ - __m256 h00i = _mm256_load_ps((float *) &h[0][0][i]); - __m256 h01i = _mm256_load_ps((float *) &h[0][1][i]); - __m256 h10i = _mm256_load_ps((float *) &h[1][0][i]); - __m256 h11i = _mm256_load_ps((float *) &h[1][1][i]); - - /* Apply precoding */ - __m256 h00 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, mask0)); - __m256 h10 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, mask0)); - __m256 h01 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, mask1)); - __m256 h11 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, mask1)); - - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); - - __m256 x0, x1; - - srslte_mat_2x2_zf_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, 2.0f / scaling); - - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); - } - - return nof_symbols; -} -#endif /* LV_HAVE_AVX */ - -// SSE implementation of ZF 2x2 CCD equalizer -#ifdef LV_HAVE_SSE - -int srslte_predecoding_ccd_2x2_zf_sse(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, - float scaling) { - uint32_t i = 0; - - for (i = 0; i < nof_symbols - 1; i += 2) { - /* Load channel */ - __m128 h00i = _mm_load_ps((float *) &h[0][0][i]); - __m128 h01i = _mm_load_ps((float *) &h[0][1][i]); - __m128 h10i = _mm_load_ps((float *) &h[1][0][i]); - __m128 h11i = _mm_load_ps((float *) &h[1][1][i]); - - /* Apply precoding */ - __m128 h00 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h10 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h01 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); - __m128 h11 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); - - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); - - __m128 x0, x1; - - srslte_mat_2x2_zf_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, 2.0f / scaling); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); - } - - return nof_symbols; -} +#if SRSLTE_SIMD_CF_SIZE != 0 +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; #endif -// Generic implementation of ZF 2x2 CCD equalizer -int srslte_predecoding_ccd_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - int nof_symbols, - float scaling) { - cf_t h00, h01, h10, h11; + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); - for (int i = 0; i < nof_symbols; i++) { + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + /* Load channel */ + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + /* Apply precoding */ + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + + srslte_simd_f_store(&csi[0][i], csi0); + srslte_simd_f_store(&csi[1][i], csi1); + } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ + + cf_t h00, h01, h10, h11, det; + for (; i < nof_symbols; i++) { // Even precoder h00 = +h[0][0][i] + h[1][0][i]; h10 = +h[0][1][i] + h[1][1][i]; h01 = +h[0][0][i] - h[1][0][i]; h11 = +h[0][1][i] - h[1][1][i]; + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); - srslte_mat_2x2_zf_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], 2.0f / scaling); + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; + + csi[0][i] = 1.0f; + csi[1][i] = 1.0f; i++; @@ -718,125 +799,82 @@ int srslte_predecoding_ccd_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], h10 = h[0][1][i] - h[1][1][i]; h01 = h[0][0][i] + h[1][0][i]; h11 = h[0][1][i] + h[1][1][i]; + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); - srslte_mat_2x2_zf_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], 2.0f / scaling); + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; + + csi[0][i] = 1.0f; + csi[1][i] = 1.0f; } return SRSLTE_SUCCESS; } -int srslte_predecoding_ccd_zf(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_layers, int nof_symbols, float scaling) -{ - if (nof_ports == 2 && nof_rxant == 2) { - if (nof_layers == 2) { -#ifdef LV_HAVE_AVX - return srslte_predecoding_ccd_2x2_zf_avx(y, h, x, nof_symbols, scaling); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_ccd_2x2_zf_sse(y, h, x, nof_symbols, scaling); -#else - return srslte_predecoding_ccd_2x2_zf_gen(y, h, x, nof_symbols, scaling); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ - } else { - DEBUG("Error predecoding CCD: Invalid number of layers %d\n", nof_layers); - return -1; - } - } else if (nof_ports == 4) { - DEBUG("Error predecoding CCD: Only 2 ports supported\n"); - } else { - DEBUG("Error predecoding CCD: Invalid combination of ports %d and rx antennax %d\n", nof_ports, nof_rxant); - } - return SRSLTE_ERROR; -} - -// AVX implementation of MMSE 2x2 CCD equalizer -#ifdef LV_HAVE_AVX - -int srslte_predecoding_ccd_2x2_mmse_avx(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, float scaling, float noise_estimate) { +static int srslte_predecoding_ccd_2x2_zf(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int nof_symbols, + float scaling) { uint32_t i = 0; + float norm = 2.0f / scaling; - for (i = 0; i < nof_symbols - 3; i += 4) { +#if SRSLTE_SIMD_CF_SIZE != 0 +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; +#endif + + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); + + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { /* Load channel */ - __m256 h00i = _mm256_load_ps((float *) &h[0][0][i]); - __m256 h01i = _mm256_load_ps((float *) &h[0][1][i]); - __m256 h10i = _mm256_load_ps((float *) &h[1][0][i]); - __m256 h11i = _mm256_load_ps((float *) &h[1][1][i]); + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); /* Apply precoding */ - __m256 h00 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, _mm256_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f))); - __m256 h10 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, _mm256_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f))); - __m256 h01 = _mm256_add_ps(h00i, _mm256_xor_ps(h10i, _mm256_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f))); - __m256 h11 = _mm256_add_ps(h01i, _mm256_xor_ps(h11i, _mm256_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f))); + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - __m256 x0, x1; + simd_cf_t x0, x1; - srslte_mat_2x2_mmse_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, 2.0f / scaling); + srslte_mat_2x2_zf_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, norm); - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ - return nof_symbols; -} -#endif /* LV_HAVE_AVX */ - -// SSE implementation of ZF 2x2 CCD equalizer -#ifdef LV_HAVE_SSE - -int srslte_predecoding_ccd_2x2_mmse_sse(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - uint32_t nof_symbols, float scaling, float noise_estimate) { - uint32_t i = 0; - - for (i = 0; i < nof_symbols - 1; i += 2) { - /* Load channel */ - __m128 h00i = _mm_load_ps((float *) &h[0][0][i]); - __m128 h01i = _mm_load_ps((float *) &h[0][1][i]); - __m128 h10i = _mm_load_ps((float *) &h[1][0][i]); - __m128 h11i = _mm_load_ps((float *) &h[1][1][i]); - - /* Apply precoding */ - __m128 h00 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h10 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(+0.0f, +0.0f, -0.0f, -0.0f))); - __m128 h01 = _mm_add_ps(h00i, _mm_xor_ps(h10i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); - __m128 h11 = _mm_add_ps(h01i, _mm_xor_ps(h11i, _mm_setr_ps(-0.0f, -0.0f, +0.0f, +0.0f))); - - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); - - __m128 x0, x1; - - srslte_mat_2x2_mmse_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, 2.0f / scaling); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); - } - - return nof_symbols; -} -#endif /* LV_HAVE_SSE */ - -// Generic implementation of ZF 2x2 CCD equalizer -int srslte_predecoding_ccd_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_symbols, float scaling, float noise_estimate) { - cf_t h00, h01, h10, h11; - - for (int i = 0; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11, det; + for (; i < nof_symbols; i++) { // Even precoder h00 = +h[0][0][i] + h[1][0][i]; h10 = +h[0][1][i] + h[1][1][i]; h01 = +h[0][0][i] - h[1][0][i]; h11 = +h[0][1][i] - h[1][1][i]; - srslte_mat_2x2_mmse_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], noise_estimate, 2.0f / scaling); + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); + + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; i++; @@ -845,26 +883,31 @@ int srslte_predecoding_ccd_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLT h10 = h[0][1][i] - h[1][1][i]; h01 = h[0][0][i] + h[1][0][i]; h11 = h[0][1][i] + h[1][1][i]; - srslte_mat_2x2_mmse_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], noise_estimate, 2.0f / scaling); + det = (h00 * h11 - h01 * h10); + det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); + + x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; + x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; } return SRSLTE_SUCCESS; } - -int srslte_predecoding_ccd_mmse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_layers, int nof_symbols, float scaling, float noise_estimate) -{ +static int srslte_predecoding_ccd_zf(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, + int nof_ports, + int nof_layers, + int nof_symbols, + float scaling) { if (nof_ports == 2 && nof_rxant == 2) { if (nof_layers == 2) { -#ifdef LV_HAVE_AVX - return srslte_predecoding_ccd_2x2_mmse_avx(y, h, x, nof_symbols, scaling, noise_estimate); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_ccd_2x2_mmse_sse(y, h, x, nof_symbols, scaling, noise_estimate); -#else - return srslte_predecoding_ccd_2x2_mmse_gen(y, h, x, nof_symbols, scaling, noise_estimate); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_ccd_2x2_zf_csi(y, h, x, csi, nof_symbols, scaling); + } else { + return srslte_predecoding_ccd_2x2_zf(y, h, x, nof_symbols, scaling); + } } else { DEBUG("Error predecoding CCD: Invalid number of layers %d\n", nof_layers); return -1; @@ -877,14 +920,215 @@ int srslte_predecoding_ccd_mmse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PO return SRSLTE_ERROR; } -#ifdef LV_HAVE_AVX +static int srslte_predecoding_ccd_2x2_mmse_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_symbols, float scaling, float noise_estimate) { + int i = 0; + float norm = 2.0f / scaling; -// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_zf_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = 1.0; +#if SRSLTE_SIMD_CF_SIZE != 0 +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; +#endif - switch(codebook_idx) { + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); + + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + /* Load channel */ + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + /* Apply precoding */ + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, noise_estimate, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + + srslte_simd_f_store(&csi[0][i], csi0); + srslte_simd_f_store(&csi[1][i], csi1); + } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ + + cf_t h00, h01, h10, h11; + for (; i < nof_symbols; i++) { + + // Even precoder + h00 = +h[0][0][i] + h[1][0][i]; + h10 = +h[0][1][i] + h[1][1][i]; + h01 = +h[0][0][i] - h[1][0][i]; + h11 = +h[0][1][i] - h[1][1][i]; + srslte_mat_2x2_mmse_csi_gen(y[0][i], + y[1][i], + h00, + h01, + h10, + h11, + &x[0][i], + &x[1][i], + &csi[0][i], + &csi[1][i], + noise_estimate, + norm); + i++; + + // Odd precoder + h00 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] - h[1][1][i]; + h01 = h[0][0][i] + h[1][0][i]; + h11 = h[0][1][i] + h[1][1][i]; + srslte_mat_2x2_mmse_csi_gen(y[0][i], + y[1][i], + h00, + h01, + h10, + h11, + &x[0][i], + &x[1][i], + &csi[0][i], + &csi[1][i], + noise_estimate, + norm); + } + return SRSLTE_SUCCESS; +} + +static int srslte_predecoding_ccd_2x2_mmse(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int nof_symbols, float scaling, float noise_estimate) { + int i = 0; + float norm = 2.0f / scaling; + +#if SRSLTE_SIMD_CF_SIZE != 0 +#if SRSLTE_SIMD_CF_SIZE == 16 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, + +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, + -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 8 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f}; +#elif SRSLTE_SIMD_CF_SIZE == 4 + float _mask1[SRSLTE_SIMD_CF_SIZE] = {+0.0f, -0.0f, +0.0f, -0.0f}; + float _mask2[SRSLTE_SIMD_CF_SIZE] = {-0.0f, +0.0f, -0.0f, +0.0f}; +#endif + + simd_f_t mask1 = srslte_simd_f_loadu(_mask1); + simd_f_t mask2 = srslte_simd_f_loadu(_mask2); + + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + /* Load channel */ + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + /* Apply precoding */ + simd_cf_t h00, h01, h10, h11; + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask1)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask1)); + h01 = srslte_simd_cf_add(h00i, srslte_simd_cf_neg_mask(h10i, mask2)); + h11 = srslte_simd_cf_add(h01i, srslte_simd_cf_neg_mask(h11i, mask2)); + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + srslte_mat_2x2_mmse_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + } +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ + + cf_t h00, h01, h10, h11; + for (; i < nof_symbols; i++) { + + // Even precoder + h00 = +h[0][0][i] + h[1][0][i]; + h10 = +h[0][1][i] + h[1][1][i]; + h01 = +h[0][0][i] - h[1][0][i]; + h11 = +h[0][1][i] - h[1][1][i]; + srslte_mat_2x2_mmse_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], noise_estimate, 2.0f / scaling); + + i++; + + // Odd precoder + h00 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] - h[1][1][i]; + h01 = h[0][0][i] + h[1][0][i]; + h11 = h[0][1][i] + h[1][1][i]; + srslte_mat_2x2_mmse_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], noise_estimate, 2.0f / scaling); + } + return SRSLTE_SUCCESS; +} + +int srslte_predecoding_ccd_mmse(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, + int nof_ports, + int nof_layers, + int nof_symbols, + float scaling, + float noise_estimate) { + if (nof_ports == 2 && nof_rxant == 2) { + if (nof_layers == 2) { + if (csi && csi[0]) + return srslte_predecoding_ccd_2x2_mmse_csi(y, h, x, csi, nof_symbols, scaling, noise_estimate); + else { + return srslte_predecoding_ccd_2x2_mmse(y, h, x, nof_symbols, scaling, noise_estimate); + } + } else { + DEBUG("Error predecoding CCD: Invalid number of layers %d\n", nof_layers); + return -1; + } + } else if (nof_ports == 4) { + DEBUG("Error predecoding CCD: Only 2 ports supported\n"); + } else { + DEBUG("Error predecoding CCD: Invalid combination of ports %d and rx antennax %d\n", nof_ports, nof_rxant); + } + return SRSLTE_ERROR; +} + +static int srslte_predecoding_multiplex_2x2_zf_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi, + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = 1.0f; + int i = 0; + + switch (codebook_idx) { case 0: norm = (float) M_SQRT2 / scaling; break; @@ -897,145 +1141,57 @@ int srslte_predecoding_multiplex_2x2_zf_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[S return SRSLTE_ERROR; } - for (int i = 0; i < nof_symbols - 3; i += 4) { - __m256 _h00 = _mm256_load_ps((float*)&(h[0][0][i])); - __m256 _h01 = _mm256_load_ps((float*)&(h[0][1][i])); - __m256 _h10 = _mm256_load_ps((float*)&(h[1][0][i])); - __m256 _h11 = _mm256_load_ps((float*)&(h[1][1][i])); +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); - __m256 h00, h01, h10, h11; + simd_cf_t h00, h01, h10, h11; switch (codebook_idx) { case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; break; case 1: - h00 = _mm256_add_ps(_h00, _h10); - h01 = _mm256_sub_ps(_h00, _h10); - h10 = _mm256_add_ps(_h01, _h11); - h11 = _mm256_sub_ps(_h01, _h11); + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); break; case 2: - h00 = _mm256_add_ps(_h00, _MM256_MULJ_PS(_h10)); - h01 = _mm256_sub_ps(_h00, _MM256_MULJ_PS(_h10)); - h10 = _mm256_add_ps(_h01, _MM256_MULJ_PS(_h11)); - h11 = _mm256_sub_ps(_h01, _MM256_MULJ_PS(_h11)); - break; - default: - DEBUG("Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); - - __m256 x0, x1; - - srslte_mat_2x2_zf_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, norm); - - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); - - } - - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_AVX */ - -#ifdef LV_HAVE_SSE - -// SSE implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_zf_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = 1.0; - - switch(codebook_idx) { - case 0: - norm = (float) M_SQRT2 / scaling; - break; - case 1: - case 2: - norm = 2.0f / scaling; - break; - default: - ERROR("Wrong codebook_idx=%d", codebook_idx); - return SRSLTE_ERROR; - } - - for (int i = 0; i < nof_symbols - 1; i += 2) { - __m128 _h00 = _mm_load_ps((float*)&(h[0][0][i])); - __m128 _h01 = _mm_load_ps((float*)&(h[0][1][i])); - __m128 _h10 = _mm_load_ps((float*)&(h[1][0][i])); - __m128 _h11 = _mm_load_ps((float*)&(h[1][1][i])); - - __m128 h00, h01, h10, h11; - switch (codebook_idx) { - case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; - break; - case 1: - h00 = _mm_add_ps(_h00, _h10); - h01 = _mm_sub_ps(_h00, _h10); - h10 = _mm_add_ps(_h01, _h11); - h11 = _mm_sub_ps(_h01, _h11); - break; - case 2: - h00 = _mm_add_ps(_h00, _MM_MULJ_PS(_h10)); - h01 = _mm_sub_ps(_h00, _MM_MULJ_PS(_h10)); - h10 = _mm_add_ps(_h01, _MM_MULJ_PS(_h11)); - h11 = _mm_sub_ps(_h01, _MM_MULJ_PS(_h11)); + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); - __m128 x0, x1; + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, norm); - srslte_mat_2x2_zf_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, norm); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + srslte_simd_f_store(&csi[i], csi0); + srslte_simd_f_store(&csi[i], csi1); } +#endif /* SRSLTE_SIMD_CF_SIZE */ - return SRSLTE_SUCCESS; -} + for (; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11; -#endif /* LV_HAVE_SSE */ - - -// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - float norm = 1.0; - - switch(codebook_idx) { - case 0: - norm = (float) M_SQRT2 / scaling; - break; - case 1: - case 2: - norm = 2.0f / scaling; - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - for (int i = 0; i < nof_symbols; i++) { - cf_t h00, h01, h10, h11, det; - - switch(codebook_idx) { + switch (codebook_idx) { case 0: h00 = h[0][0][i]; h01 = h[1][0][i]; @@ -1049,168 +1205,252 @@ int srslte_predecoding_multiplex_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[S h11 = h[0][1][i] - h[1][1][i]; break; case 2: - h00 = h[0][0][i] + _Complex_I*h[1][0][i]; - h01 = h[0][0][i] - _Complex_I*h[1][0][i]; - h10 = h[0][1][i] + _Complex_I*h[1][1][i]; - h11 = h[0][1][i] - _Complex_I*h[1][1][i]; + h00 = h[0][0][i] + _Complex_I * h[1][0][i]; + h01 = h[0][0][i] - _Complex_I * h[1][0][i]; + h10 = h[0][1][i] + _Complex_I * h[1][1][i]; + h11 = h[0][1][i] - _Complex_I * h[1][1][i]; break; default: fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); return SRSLTE_ERROR; } - det = (h00 * h11 - h01 * h10); + cf_t det = (h00 * h11 - h01 * h10); det = conjf(det) * (norm / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det))); x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det; x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det; + + csi[i] = 1.0f; + csi[i] = 1.0f; } return SRSLTE_SUCCESS; } -#ifdef LV_HAVE_AVX - -// AVX implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_mmse_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) { - float norm = 1.0; - - switch(codebook_idx) { - case 0: - norm = (float) M_SQRT2 / scaling; - break; - case 1: - case 2: - norm = 2.0f / scaling; - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - for (int i = 0; i < nof_symbols; i += 4) { - __m256 _h00 = _mm256_load_ps((float*)&(h[0][0][i])); - __m256 _h01 = _mm256_load_ps((float*)&(h[0][1][i])); - __m256 _h10 = _mm256_load_ps((float*)&(h[1][0][i])); - __m256 _h11 = _mm256_load_ps((float*)&(h[1][1][i])); - - __m256 h00, h01, h10, h11; - switch (codebook_idx) { - case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; - break; - case 1: - h00 = _mm256_add_ps(_h00, _h10); - h01 = _mm256_sub_ps(_h00, _h10); - h10 = _mm256_add_ps(_h01, _h11); - h11 = _mm256_sub_ps(_h01, _h11); - break; - case 2: - h00 = _mm256_add_ps(_h00, _MM256_MULJ_PS(_h10)); - h01 = _mm256_sub_ps(_h00, _MM256_MULJ_PS(_h10)); - h10 = _mm256_add_ps(_h01, _MM256_MULJ_PS(_h11)); - h11 = _mm256_sub_ps(_h01, _MM256_MULJ_PS(_h11)); - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - __m256 y0 = _mm256_load_ps((float *) &y[0][i]); - __m256 y1 = _mm256_load_ps((float *) &y[1][i]); - - __m256 x0, x1; - - srslte_mat_2x2_mmse_avx(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, norm); - - _mm256_store_ps((float *) &x[0][i], x0); - _mm256_store_ps((float *) &x[1][i], x1); - - } - - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_AVX */ - - -#ifdef LV_HAVE_SSE - -// SSE implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_mmse_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) { - float norm; - - switch(codebook_idx) { - case 0: - norm = (float) M_SQRT2 / scaling; - break; - case 1: - case 2: - norm = 2.0f / scaling; - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - for (int i = 0; i < nof_symbols - 1; i += 2) { - __m128 _h00 = _mm_load_ps((float*)&(h[0][0][i])); - __m128 _h01 = _mm_load_ps((float*)&(h[0][1][i])); - __m128 _h10 = _mm_load_ps((float*)&(h[1][0][i])); - __m128 _h11 = _mm_load_ps((float*)&(h[1][1][i])); - - __m128 h00, h01, h10, h11; - switch (codebook_idx) { - case 0: - h00 = _h00; - h01 = _h10; - h10 = _h01; - h11 = _h11; - break; - case 1: - h00 = _mm_add_ps(_h00, _h10); - h01 = _mm_sub_ps(_h00, _h10); - h10 = _mm_add_ps(_h01, _h11); - h11 = _mm_sub_ps(_h01, _h11); - break; - case 2: - h00 = _mm_add_ps(_h00, _MM_MULJ_PS(_h10)); - h01 = _mm_sub_ps(_h00, _MM_MULJ_PS(_h10)); - h10 = _mm_add_ps(_h01, _MM_MULJ_PS(_h11)); - h11 = _mm_sub_ps(_h01, _MM_MULJ_PS(_h11)); - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - __m128 y0 = _mm_load_ps((float *) &y[0][i]); - __m128 y1 = _mm_load_ps((float *) &y[1][i]); - - __m128 x0, x1; - - srslte_mat_2x2_mmse_sse(y0, y1, h00, h01, h10, h11, &x0, &x1, noise_estimate, norm); - - _mm_store_ps((float *) &x[0][i], x0); - _mm_store_ps((float *) &x[1][i], x1); - - } - - return SRSLTE_SUCCESS; -} -#endif /* LV_HAVE_SSE */ - // Generic implementation of ZF 2x2 Spatial Multiplexity equalizer -int srslte_predecoding_multiplex_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) { +static int srslte_predecoding_multiplex_2x2_zf(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = 1.0f; + int i = 0; + + switch (codebook_idx) { + case 0: + norm = (float) M_SQRT2 / scaling; + break; + case 1: + case 2: + norm = 2.0f / scaling; + break; + default: + ERROR("Wrong codebook_idx=%d", codebook_idx); + return SRSLTE_ERROR; + } + +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + simd_cf_t h00, h01, h10, h11; + switch (codebook_idx) { + case 0: + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; + break; + case 1: + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); + break; + case 2: + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_zf_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + + } +#endif /* SRSLTE_SIMD_CF_SIZE */ + + for (; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11; + + switch (codebook_idx) { + case 0: + h00 = h[0][0][i]; + h01 = h[1][0][i]; + h10 = h[0][1][i]; + h11 = h[1][1][i]; + break; + case 1: + h00 = h[0][0][i] + h[1][0][i]; + h01 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] + h[1][1][i]; + h11 = h[0][1][i] - h[1][1][i]; + break; + case 2: + h00 = h[0][0][i] + _Complex_I * h[1][0][i]; + h01 = h[0][0][i] - _Complex_I * h[1][0][i]; + h10 = h[0][1][i] + _Complex_I * h[1][1][i]; + h11 = h[0][1][i] - _Complex_I * h[1][1][i]; + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + srslte_mat_2x2_zf_gen(y[0][i], y[1][i], h00, h01, h10, h11, &x[0][i], &x[1][i], norm); + } + return SRSLTE_SUCCESS; +} + +// Generic implementation of ZF 2x2 Spatial Multiplexity equalizer +static int srslte_predecoding_multiplex_2x2_mmse_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int codebook_idx, + int nof_symbols, + float scaling, + float noise_estimate) { + float norm = 1.0f; + int i = 0; + + switch (codebook_idx) { + case 0: + norm = (float) M_SQRT2 / scaling; + break; + case 1: + case 2: + norm = 2.0f / scaling; + break; + default: + ERROR("Wrong codebook_idx=%d", codebook_idx); + return SRSLTE_ERROR; + } + +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + simd_cf_t h00, h01, h10, h11; + switch (codebook_idx) { + case 0: + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; + break; + case 1: + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); + break; + case 2: + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, noise_estimate, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + + srslte_simd_f_store(&csi[0][i], csi0); + srslte_simd_f_store(&csi[1][i], csi1); + } +#endif /* SRSLTE_SIMD_CF_SIZE */ + + for (; i < nof_symbols; i++) { + cf_t h00, h01, h10, h11; + + switch (codebook_idx) { + case 0: + h00 = h[0][0][i]; + h01 = h[1][0][i]; + h10 = h[0][1][i]; + h11 = h[1][1][i]; + break; + case 1: + h00 = h[0][0][i] + h[1][0][i]; + h01 = h[0][0][i] - h[1][0][i]; + h10 = h[0][1][i] + h[1][1][i]; + h11 = h[0][1][i] - h[1][1][i]; + break; + case 2: + h00 = h[0][0][i] + _Complex_I * h[1][0][i]; + h01 = h[0][0][i] - _Complex_I * h[1][0][i]; + h10 = h[0][1][i] + _Complex_I * h[1][1][i]; + h11 = h[0][1][i] - _Complex_I * h[1][1][i]; + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + srslte_mat_2x2_mmse_csi_gen(y[0][i], + y[1][i], + h00, + h01, + h10, + h11, + &x[0][i], + &x[1][i], + &csi[0][i], + &csi[1][i], + noise_estimate, + norm); + } + return SRSLTE_SUCCESS; +} + +static int srslte_predecoding_multiplex_2x2_mmse(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int codebook_idx, + int nof_symbols, + float scaling, + float noise_estimate) { float norm = 1.0; + int i = 0; switch(codebook_idx) { case 0: @@ -1225,7 +1465,51 @@ int srslte_predecoding_multiplex_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h return SRSLTE_ERROR; } - for (int i = 0; i < nof_symbols; i++) { +#if SRSLTE_SIMD_CF_SIZE != 0 + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t h00i = srslte_simd_cfi_load(&h[0][0][i]); + simd_cf_t h01i = srslte_simd_cfi_load(&h[0][1][i]); + simd_cf_t h10i = srslte_simd_cfi_load(&h[1][0][i]); + simd_cf_t h11i = srslte_simd_cfi_load(&h[1][1][i]); + + simd_cf_t h00, h01, h10, h11; + switch(codebook_idx) { + case 0: + h00 = h00i; + h01 = h10i; + h10 = h01i; + h11 = h11i; + break; + case 1: + h00 = srslte_simd_cf_add(h00i, h10i); + h01 = srslte_simd_cf_sub(h00i, h10i); + h10 = srslte_simd_cf_add(h01i, h11i); + h11 = srslte_simd_cf_sub(h01i, h11i); + break; + case 2: + h00 = srslte_simd_cf_add(h00i, srslte_simd_cf_mulj(h10i)); + h01 = srslte_simd_cf_sub(h00i, srslte_simd_cf_mulj(h10i)); + h10 = srslte_simd_cf_add(h01i, srslte_simd_cf_mulj(h11i)); + h11 = srslte_simd_cf_sub(h01i, srslte_simd_cf_mulj(h11i)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + simd_cf_t y0 = srslte_simd_cfi_load(&y[0][i]); + simd_cf_t y1 = srslte_simd_cfi_load(&y[1][i]); + + simd_cf_t x0, x1; + simd_f_t csi0, csi1; + srslte_mat_2x2_mmse_csi_simd(y0, y1, h00, h01, h10, h11, &x0, &x1, &csi0, &csi1, noise_estimate, norm); + + srslte_simd_cfi_store(&x[0][i], x0); + srslte_simd_cfi_store(&x[1][i], x1); + } +#endif /* SRSLTE_SIMD_CF_SIZE */ + + for (; i < nof_symbols; i++) { cf_t h00, h01, h10, h11; switch(codebook_idx) { @@ -1257,134 +1541,62 @@ int srslte_predecoding_multiplex_2x2_mmse_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h return SRSLTE_SUCCESS; } -#ifdef LV_HAVE_AVX -// Generic implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer -int srslte_predecoding_multiplex_2x1_mrc_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - - for (int i = 0; i < nof_symbols - 3; i += 4) { - __m256 _h00 = _mm256_load_ps((float*)&(h[0][0][i])); - __m256 _h01 = _mm256_load_ps((float*)&(h[0][1][i])); - __m256 _h10 = _mm256_load_ps((float*)&(h[1][0][i])); - __m256 _h11 = _mm256_load_ps((float*)&(h[1][1][i])); - - __m256 h0, h1; - switch (codebook_idx) { - case 0: - h0 = _mm256_add_ps(_h00, _h10); - h1 = _mm256_add_ps(_h01, _h11); - break; - case 1: - h0 = _mm256_sub_ps(_h00, _h10); - h1 = _mm256_sub_ps(_h01, _h11); - break; - case 2: - h0 = _mm256_add_ps(_h00, _MM256_MULJ_PS(_h10)); - h1 = _mm256_add_ps(_h01, _MM256_MULJ_PS(_h11)); - break; - case 3: - h0 = _mm256_sub_ps(_h00, _MM256_MULJ_PS(_h10)); - h1 = _mm256_sub_ps(_h01, _MM256_MULJ_PS(_h11)); - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - __m256 h0_2 = _mm256_mul_ps(h0, h0); - __m256 h1_2 = _mm256_mul_ps(h1, h1); - __m256 hh0 = _mm256_add_ps(_mm256_movehdup_ps(h0_2), _mm256_moveldup_ps(h0_2)); - __m256 hh1 = _mm256_add_ps(_mm256_movehdup_ps(h1_2), _mm256_moveldup_ps(h1_2)); - __m256 hh = _mm256_add_ps(hh0, hh1); - __m256 hhrec = _mm256_rcp_ps(hh); - - hhrec = _mm256_mul_ps(hhrec, _mm256_set1_ps((float) M_SQRT2 / scaling)); - __m256 y0 = _mm256_load_ps((float*)&y[0][i]); - __m256 y1 = _mm256_load_ps((float*)&y[1][i]); - - __m256 x0 = _mm256_add_ps(_MM256_PROD_PS(_MM256_CONJ_PS(h0), y0), _MM256_PROD_PS(_MM256_CONJ_PS(h1), y1)); - x0 = _mm256_mul_ps(hhrec, x0); - - _mm256_store_ps((float*)&x[0][i], x0); - - } - - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_AVX */ - - -// SSE implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer -#ifdef LV_HAVE_SSE - -int srslte_predecoding_multiplex_2x1_mrc_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { - - for (int i = 0; i < nof_symbols - 1; i += 2) { - __m128 _h00 = _mm_load_ps((float*)&(h[0][0][i])); - __m128 _h01 = _mm_load_ps((float*)&(h[0][1][i])); - __m128 _h10 = _mm_load_ps((float*)&(h[1][0][i])); - __m128 _h11 = _mm_load_ps((float*)&(h[1][1][i])); - - __m128 h0, h1; - switch (codebook_idx) { - case 0: - h0 = _mm_add_ps(_h00, _h10); - h1 = _mm_add_ps(_h01, _h11); - break; - case 1: - h0 = _mm_sub_ps(_h00, _h10); - h1 = _mm_sub_ps(_h01, _h11); - break; - case 2: - h0 = _mm_add_ps(_h00, _MM_MULJ_PS(_h10)); - h1 = _mm_add_ps(_h01, _MM_MULJ_PS(_h11)); - break; - case 3: - h0 = _mm_sub_ps(_h00, _MM_MULJ_PS(_h10)); - h1 = _mm_sub_ps(_h01, _MM_MULJ_PS(_h11)); - break; - default: - fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); - return SRSLTE_ERROR; - } - - __m128 h0_2 = _mm_mul_ps(h0, h0); - __m128 h1_2 = _mm_mul_ps(h1, h1); - __m128 hh0 = _mm_add_ps(_mm_movehdup_ps(h0_2), _mm_moveldup_ps(h0_2)); - __m128 hh1 = _mm_add_ps(_mm_movehdup_ps(h1_2), _mm_moveldup_ps(h1_2)); - __m128 hh = _mm_add_ps(hh0, hh1); - __m128 hhrec = _mm_rcp_ps(hh); - - hhrec = _mm_mul_ps(hhrec, _mm_set1_ps((float) M_SQRT2 / scaling)); - - __m128 y0 = _mm_load_ps((float*)&y[0][i]); - __m128 y1 = _mm_load_ps((float*)&y[1][i]); - - __m128 x0 = _mm_add_ps(_MM_PROD_PS(_MM_CONJ_PS(h0), y0), _MM_PROD_PS(_MM_CONJ_PS(h1), y1)); - x0 = _mm_mul_ps(hhrec, x0); - - _mm_store_ps((float*)&x[0][i], x0); - - } - - return SRSLTE_SUCCESS; -} - -#endif /* LV_HAVE_SSE */ - -// Generic implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer -int srslte_predecoding_multiplex_2x1_mrc_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int codebook_idx, int nof_symbols, float scaling) { +// Implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer +static int srslte_predecoding_multiplex_2x1_mrc(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int codebook_idx, + int nof_symbols, + float scaling) { float norm = (float) M_SQRT2 / scaling; + int i = 0; - for (int i = 0; i < nof_symbols; i += 1) { +#if SRSLTE_SIMD_CF_SIZE != 0 + simd_f_t _norm = srslte_simd_f_set1(norm); + + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t x0 = srslte_simd_cf_set1(0.0f); + simd_f_t hh = srslte_simd_f_set1(0.0f); + + for (int k = 0; k < 2; k++) { + simd_cf_t h0xi = srslte_simd_cfi_load(&h[0][k][i]); + simd_cf_t h1xi = srslte_simd_cfi_load(&h[1][k][i]); + simd_cf_t yx = srslte_simd_cfi_load(&y[k][i]); + + simd_cf_t hx; + switch (codebook_idx) { + case 0: + hx = srslte_simd_cf_add(h0xi, h1xi); + break; + case 1: + hx = srslte_simd_cf_sub(h0xi, h1xi); + break; + case 2: + hx = srslte_simd_cf_add(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + case 3: + hx = srslte_simd_cf_sub(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + hh = srslte_simd_f_add(srslte_simd_cf_re(srslte_simd_cf_conjprod(hx, hx)), hh); + x0 = srslte_simd_cf_add(srslte_simd_cf_conjprod(yx, hx), x0); + } + + hh = srslte_simd_f_mul(_norm, srslte_simd_f_rcp(hh)); + srslte_simd_cfi_store(&x[0][i], srslte_simd_cf_mul(x0, hh)); + } +#endif /* SRSLTE_SIMD_CF_SIZE */ + + for (; i < nof_symbols; i += 1) { cf_t h0, h1; float hh; - switch(codebook_idx) { + switch (codebook_idx) { case 0: h0 = h[0][0][i] + h[1][0][i]; h1 = h[0][1][i] + h[1][1][i]; @@ -1413,46 +1625,135 @@ int srslte_predecoding_multiplex_2x1_mrc_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[ return SRSLTE_SUCCESS; } -int srslte_predecoding_multiplex(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_layers, int codebook_idx, int nof_symbols, - float scaling, float noise_estimate) -{ +// Generic implementation of MRC 2x1 (two antennas into one layer) Spatial Multiplexing equalizer +static int srslte_predecoding_multiplex_2x1_mrc_csi(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi, + int codebook_idx, + int nof_symbols, + float scaling) { + float norm = (float) M_SQRT2 / scaling; + int i = 0; + +#if SRSLTE_SIMD_CF_SIZE != 0 + simd_f_t _norm = srslte_simd_f_set1(norm); + + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t x0 = srslte_simd_cf_set1(0.0f); + simd_f_t hh = srslte_simd_f_set1(0.0f); + + for (int k = 0; k < 2; k++) { + simd_cf_t h0xi = srslte_simd_cfi_load(&h[0][k][i]); + simd_cf_t h1xi = srslte_simd_cfi_load(&h[1][k][i]); + simd_cf_t yx = srslte_simd_cfi_load(&y[k][i]); + + simd_cf_t hx; + switch (codebook_idx) { + case 0: + hx = srslte_simd_cf_add(h0xi, h1xi); + break; + case 1: + hx = srslte_simd_cf_sub(h0xi, h1xi); + break; + case 2: + hx = srslte_simd_cf_add(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + case 3: + hx = srslte_simd_cf_sub(h0xi, srslte_simd_cf_mulj(h1xi)); + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + hh = srslte_simd_f_add(srslte_simd_cf_re(srslte_simd_cf_conjprod(hx, hx)), hh); + x0 = srslte_simd_cf_add(srslte_simd_cf_conjprod(yx, hx), x0); + } + + hh = srslte_simd_f_mul(_norm, srslte_simd_f_rcp(hh)); + srslte_simd_cfi_store(&x[0][i], srslte_simd_cf_mul(x0, hh)); + srslte_simd_f_store(&csi[i], srslte_simd_f_mul(srslte_simd_f_rcp(hh), srslte_simd_f_set1((float) M_SQRT1_2))); + } +#endif /* SRSLTE_SIMD_CF_SIZE */ + + for (; i < nof_symbols; i += 1) { + cf_t h0, h1; + float hh, _csi; + + switch (codebook_idx) { + case 0: + h0 = h[0][0][i] + h[1][0][i]; + h1 = h[0][1][i] + h[1][1][i]; + break; + case 1: + h0 = h[0][0][i] - h[1][0][i]; + h1 = h[0][1][i] - h[1][1][i]; + break; + case 2: + h0 = h[0][0][i] + _Complex_I * h[1][0][i]; + h1 = h[0][1][i] + _Complex_I * h[1][1][i]; + break; + case 3: + h0 = h[0][0][i] - _Complex_I * h[1][0][i]; + h1 = h[0][1][i] - _Complex_I * h[1][1][i]; + break; + default: + fprintf(stderr, "Wrong codebook_idx=%d\n", codebook_idx); + return SRSLTE_ERROR; + } + + _csi = crealf(h0) * crealf(h0) + cimagf(h0) * cimagf(h0) + crealf(h1) * crealf(h1) + cimagf(h1) * cimagf(h1); + hh = norm / _csi; + + x[0][i] = (conjf(h0) * y[0][i] + conjf(h1) * y[1][i]) * hh; + csi[i] = _csi / norm * (float) M_SQRT1_2; + } + return SRSLTE_SUCCESS; +} + +static int srslte_predecoding_multiplex(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + float *csi[SRSLTE_MAX_CODEWORDS], + int nof_rxant, + int nof_ports, + int nof_layers, + int codebook_idx, + int nof_symbols, + float scaling, + float noise_estimate) { if (nof_ports == 2 && nof_rxant <= 2) { if (nof_layers == 2) { switch (mimo_decoder) { case SRSLTE_MIMO_DECODER_ZF: -#ifdef LV_HAVE_AVX - return srslte_predecoding_multiplex_2x2_zf_avx(y, h, x, codebook_idx, nof_symbols, scaling); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_multiplex_2x2_zf_sse(y, h, x, codebook_idx, nof_symbols, scaling); -#else - return srslte_predecoding_multiplex_2x2_zf_gen(y, h, x, codebook_idx, nof_symbols, scaling); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_multiplex_2x2_zf_csi(y, h, x, csi[0], codebook_idx, nof_symbols, scaling); + } else { + return srslte_predecoding_multiplex_2x2_zf(y, h, x, codebook_idx, nof_symbols, scaling); + } break; case SRSLTE_MIMO_DECODER_MMSE: -#ifdef LV_HAVE_AVX - return srslte_predecoding_multiplex_2x2_mmse_avx(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_multiplex_2x2_mmse_sse(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); -#else - return srslte_predecoding_multiplex_2x2_mmse_gen(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_multiplex_2x2_mmse_csi(y, + h, + x, + csi, + codebook_idx, + nof_symbols, + scaling, + noise_estimate); + } else { + return srslte_predecoding_multiplex_2x2_mmse(y, h, x, codebook_idx, nof_symbols, scaling, noise_estimate); + } break; } } else { -#ifdef LV_HAVE_AVX - return srslte_predecoding_multiplex_2x1_mrc_avx(y, h, x, codebook_idx, nof_symbols, scaling); -#else -#ifdef LV_HAVE_SSE - return srslte_predecoding_multiplex_2x1_mrc_sse(y, h, x, codebook_idx, nof_symbols, scaling); -#else - return srslte_predecoding_multiplex_2x1_mrc_gen(y, h, x, codebook_idx, nof_symbols, scaling); -#endif /* LV_HAVE_SSE */ -#endif /* LV_HAVE_AVX */ + if (csi && csi[0]) { + return srslte_predecoding_multiplex_2x1_mrc_csi(y, h, x, csi[0], codebook_idx, nof_symbols, scaling); + } else { + return srslte_predecoding_multiplex_2x1_mrc(y, h, x, codebook_idx, nof_symbols, scaling); + } } } else if (nof_ports == 4) { DEBUG("Error predecoding multiplex: not implemented for %d Tx ports", nof_ports); @@ -1468,7 +1769,7 @@ void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo_decoder) { /* 36.211 v10.3.0 Section 6.3.4 */ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], float *csi, int nof_rxant, int nof_ports, int nof_layers, + cf_t *x[SRSLTE_MAX_LAYERS], float *csi[SRSLTE_MAX_CODEWORDS], int nof_rxant, int nof_ports, int nof_layers, int codebook_idx, int nof_symbols, srslte_mimo_type_t type, float scaling, float noise_estimate) { @@ -1488,10 +1789,10 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] if (nof_layers >= 2 && nof_layers <= 4) { switch (mimo_decoder) { case SRSLTE_MIMO_DECODER_ZF: - return srslte_predecoding_ccd_zf(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling); + return srslte_predecoding_ccd_zf(y, h, x, csi, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling); break; case SRSLTE_MIMO_DECODER_MMSE: - return srslte_predecoding_ccd_mmse(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling, noise_estimate); + return srslte_predecoding_ccd_mmse(y, h, x, csi, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling, noise_estimate); break; } } else { @@ -1510,7 +1811,7 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: if (nof_ports == nof_layers) { - return srslte_predecoding_diversity_multi(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); + return srslte_predecoding_diversity_multi(y, h, x, csi, nof_rxant, nof_ports, nof_symbols, scaling); } else { fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); @@ -1518,7 +1819,7 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] } break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: - return srslte_predecoding_multiplex(y, h, x, nof_rxant, nof_ports, nof_layers, codebook_idx, nof_symbols, + return srslte_predecoding_multiplex(y, h, x, csi, nof_rxant, nof_ports, nof_layers, codebook_idx, nof_symbols, scaling, noise_estimate); default: return SRSLTE_ERROR; diff --git a/lib/src/phy/phch/pcfich.c b/lib/src/phy/phch/pcfich.c index 6b00e768a..c6f1fe127 100644 --- a/lib/src/phy/phch/pcfich.c +++ b/lib/src/phy/phch/pcfich.c @@ -221,7 +221,7 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P /* no need for layer demapping */ srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, NULL, q->nof_rx_antennas, q->nof_symbols, 1.0f, noise_estimate); } else { - srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f); + srslte_predecoding_diversity_multi(q_symbols, q_ce, x, NULL, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports); } diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index 83f681f8f..1c40333e8 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -492,7 +492,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA /* no need for layer demapping */ srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, NULL, q->nof_rx_antennas, nof_symbols, 1.0f, noise_estimate/2); } else { - srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f); + srslte_predecoding_diversity_multi(q->symbols, q->ce, x, NULL, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports); } diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index c59956a71..6e7a3b33c 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -402,7 +402,7 @@ int srslte_pdsch_enable_csi(srslte_pdsch_t *q, bool enable) { if (enable) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (!q->csi[i]) { - q->csi[i] = srslte_vec_malloc(sizeof(float) * q->max_re); + q->csi[i] = srslte_vec_malloc(sizeof(float) * q->max_re * 2); if (!q->csi[i]) { return SRSLTE_ERROR; } @@ -757,7 +757,7 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } // Pre-decoder - if (srslte_predecoding_type(q->symbols, q->ce, x, q->csi[0], q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, + if (srslte_predecoding_type(q->symbols, q->ce, x, q->csi, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, pdsch_scaling, noise_estimate)<0) { DEBUG("Error predecoding\n"); return SRSLTE_ERROR; diff --git a/lib/src/phy/phch/phich.c b/lib/src/phy/phch/phich.c index 15aa4db88..21bfb040b 100644 --- a/lib/src/phy/phch/phich.c +++ b/lib/src/phy/phch/phich.c @@ -241,7 +241,7 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS], /* no need for layer demapping */ srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, NULL, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, 1.0f, noise_estimate); } else { - srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f); + srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, NULL, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f); srslte_layerdemap_diversity(x, q->d0, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports); } DEBUG("Recv!!: \n"); diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index b679e00f9..f419ea826 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -130,7 +130,7 @@ int srslte_sch_init(srslte_sch_t *q) { goto clean; } bzero(q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12); - q->ul_interleaver = srslte_vec_malloc(sizeof(uint16_t)*SRSLTE_MAX_PRB*12*12*12); + q->ul_interleaver = srslte_vec_malloc(sizeof(uint32_t)*SRSLTE_MAX_PRB*12*12*12); if (!q->ul_interleaver) { goto clean; } @@ -577,7 +577,7 @@ int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu * Profiling show that the computation of this matrix is neglegible. */ static void ulsch_interleave_gen(uint32_t H_prime_total, uint32_t N_pusch_symbs, uint32_t Qm, - uint8_t *ri_present, uint16_t *interleaver_lut) + uint8_t *ri_present, uint32_t *interleaver_lut) { uint32_t rows = H_prime_total/N_pusch_symbs; uint32_t cols = N_pusch_symbs; @@ -599,7 +599,7 @@ static void ulsch_interleave_gen(uint32_t H_prime_total, uint32_t N_pusch_symbs, /* UL-SCH channel interleaver according to 5.2.2.8 of 36.212 */ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits, - uint8_t *ri_present, uint16_t *inteleaver_lut) + uint8_t *ri_present, uint32_t *inteleaver_lut) { // Prepare ri_bits for fast search using temp_buffer @@ -611,7 +611,7 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, // Genearate interleaver table and interleave bits ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut); - srslte_bit_interleave(g_bits, q_bits, inteleaver_lut, H_prime_total*Qm); + srslte_bit_interleave_i(g_bits, q_bits, inteleaver_lut, H_prime_total*Qm); // Reset temp_buffer because will be reused next time if (nof_ri_bits > 0) { @@ -624,7 +624,7 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, /* UL-SCH channel deinterleaver according to 5.2.2.8 of 36.212 */ void ulsch_deinterleave(int16_t *q_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, int16_t *g_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits, - uint8_t *ri_present, uint16_t *inteleaver_lut) + uint8_t *ri_present, uint32_t *inteleaver_lut) { // Prepare ri_bits for fast search using temp_buffer if (nof_ri_bits > 0) { @@ -634,8 +634,8 @@ void ulsch_deinterleave(int16_t *q_bits, uint32_t Qm, uint32_t H_prime_total, } // Generate interleaver table and interleave samples - ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut); - srslte_vec_lut_sss(q_bits, inteleaver_lut, g_bits, H_prime_total*Qm); + ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut); + srslte_vec_lut_sis(q_bits, inteleaver_lut, g_bits, H_prime_total*Qm); // Reset temp_buffer because will be reused next time if (nof_ri_bits > 0) { diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index b66cf5b53..38355af92 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -41,7 +41,7 @@ #define MAX_TIME_OFFSET 128 -#define TRACK_MAX_LOST 4 +#define TRACK_MAX_LOST 100 #define TRACK_FRAME_SIZE 32 #define FIND_NOF_AVG_FRAMES 4 #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index f4e97fad6..674c1da81 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -205,6 +205,163 @@ void srslte_bit_interleaver_run(srslte_bit_interleaver_t *q, uint8_t *input, uin } +void srslte_bit_interleave_i(uint8_t *input, uint8_t *output, uint32_t *interleaver, uint32_t nof_bits) { + srslte_bit_interleave_i_w_offset(input, output, interleaver, nof_bits, 0); +} + +void srslte_bit_interleave_i_w_offset(uint8_t *input, uint8_t *output, uint32_t *interleaver, uint32_t nof_bits, uint32_t w_offset) { + uint32_t st=0, w_offset_p=0; + static const uint8_t mask[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + + if (w_offset < 8 && w_offset > 0) { + st=1; + for (uint32_t j=0;j<8-w_offset;j++) { + uint32_t i_p = interleaver[j]; + if (input[i_p/8] & mask[i_p%8]) { + output[0] |= mask[j+w_offset]; + } else { + output[0] &= ~(mask[j+w_offset]); + } + } + 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); + + union { + uint8_t v[8]; + __m64 m64; + } a, b, c; + + union { + __m128i m128; + uint16_t u32[4]; + 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; + } v16; + struct { + uint32_t i0, i1, i2, i3; + } v32; + } ipx1, ipx2, epx1, epx2; + for (uint32_t i = st; i < nof_bits / 8; i++) { + ipx1.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8 + 0) - w_offset_p)); + epx1.m128 = _mm_shuffle_epi8(ipx1.m128, _mm_set_epi8(0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C)); + ipx2.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8 + 4) - w_offset_p)); + epx2.m128 = _mm_shuffle_epi8(ipx2.m128, _mm_set_epi8(0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C, + 0x00, 0x04, 0x08, 0x0C)); + + epx1.m128 = _mm_blendv_epi8(epx2.m128, epx1.m128, _mm_setr_epi8(+1, +1, +1, +1, + -1, -1, -1, -1, + +1, +1, +1, +1, + -1, -1, -1, -1)); + + b.m64 = _mm_and_si64(epx1.m64.reg_a, _mm_set1_pi8(0x7)); + b.m64 = _mm_shuffle_pi8(m64mask, b.m64); + + ipx1.m128 = _mm_srli_epi32(ipx1.m128, 3); + ipx2.m128 = _mm_srli_epi32(ipx2.m128, 3); + + a.m64 = _mm_set_pi8(input[ipx1.v32.i0], + input[ipx1.v32.i1], + input[ipx1.v32.i2], + input[ipx1.v32.i3], + input[ipx2.v32.i0], + input[ipx2.v32.i1], + input[ipx2.v32.i2], + input[ipx2.v32.i3]); + + 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 /* Disabled */ + /* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */ + uint8_t *output2 = malloc(nof_bits/8); + for (uint32_t i=st;i #include "srslte/phy/utils/mat.h" -#include "srslte/phy/utils/simd.h" #include "srslte/phy/utils/vector.h" +#include "srslte/phy/utils/vector_simd.h" bool zf_solver = false; @@ -378,6 +378,98 @@ bool test_mmse_solver_avx(void) { #endif /* LV_HAVE_AVX */ +#if SRSLTE_SIMD_CF_SIZE != 0 + +bool test_zf_solver_simd(void) { + cf_t cf_error0, cf_error1; + float error = 0.0f; + + cf_t x0_gold_1 = RANDOM_CF(); + cf_t x1_gold_1 = RANDOM_CF(); + cf_t h00_1 = RANDOM_CF(); + cf_t h01_1 = RANDOM_CF(); + cf_t h10_1 = RANDOM_CF(); + cf_t h11_1 = (1 - h01_1 * h10_1) / h00_1; + cf_t y0_1 = x0_gold_1 * h00_1 + x1_gold_1 * h01_1; + cf_t y1_1 = x0_gold_1 * h10_1 + x1_gold_1 * h11_1; + + simd_cf_t _y0 = srslte_simd_cf_set1(y0_1); + simd_cf_t _y1 = srslte_simd_cf_set1(y1_1); + + simd_cf_t _h00 = srslte_simd_cf_set1(h00_1); + simd_cf_t _h01 = srslte_simd_cf_set1(h01_1); + simd_cf_t _h10 = srslte_simd_cf_set1(h10_1); + simd_cf_t _h11 = srslte_simd_cf_set1(h11_1); + + simd_cf_t _x0, _x1; + + srslte_mat_2x2_zf_simd(_y0, _y1, _h00, _h01, _h10, _h11, &_x0, &_x1, 1.0f); + + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x0[SRSLTE_SIMD_CF_SIZE]; + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x1[SRSLTE_SIMD_CF_SIZE]; + + srslte_simd_cfi_store(x0, _x0); + srslte_simd_cfi_store(x1, _x1); + + cf_error0 = x0[1] - x0_gold_1; + cf_error1 = x1[1] - x1_gold_1; + error += crealf(cf_error0) * crealf(cf_error0) + cimagf(cf_error0) * cimagf(cf_error0) + + crealf(cf_error1) * crealf(cf_error1) + cimagf(cf_error1) * cimagf(cf_error1); + + return (error < 1e-3); +} + +bool test_mmse_solver_simd(void) { + cf_t cf_error0, cf_error1; + float error = 0.0f; + + cf_t x0_gold[SRSLTE_SIMD_CF_SIZE]; + cf_t x1_gold[SRSLTE_SIMD_CF_SIZE]; + cf_t h00[SRSLTE_SIMD_CF_SIZE]; + cf_t h01[SRSLTE_SIMD_CF_SIZE]; + cf_t h10[SRSLTE_SIMD_CF_SIZE]; + cf_t h11[SRSLTE_SIMD_CF_SIZE]; + cf_t y0[SRSLTE_SIMD_CF_SIZE]; + cf_t y1[SRSLTE_SIMD_CF_SIZE]; + for (int i = 0; i < SRSLTE_SIMD_CF_SIZE; i++) { + x0_gold[i] = RANDOM_CF(); + x1_gold[i] = RANDOM_CF(); + h00[i] = RANDOM_CF(); + h01[i] = RANDOM_CF(); + h10[i] = RANDOM_CF(); + h11[i] = (1 - h01[i] * h10[i]) / h00[i]; + y0[i] = x0_gold[i] * h00[i]+ x1_gold[i] * h01[i]; + y1[i] = x0_gold[i] * h10[i] + x1_gold[i] * h11[i]; + } + + simd_cf_t _y0 = srslte_simd_cfi_loadu(y0); + simd_cf_t _y1 = srslte_simd_cfi_loadu(y1); + + simd_cf_t _h00 = srslte_simd_cfi_loadu(h00); + simd_cf_t _h01 = srslte_simd_cfi_loadu(h01); + simd_cf_t _h10 = srslte_simd_cfi_loadu(h10); + simd_cf_t _h11 = srslte_simd_cfi_loadu(h11); + + simd_cf_t _x0, _x1; + + srslte_mat_2x2_mmse_simd(_y0, _y1, _h00, _h01, _h10, _h11, &_x0, &_x1, 0.0f, 1.0f); + + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x0[SRSLTE_SIMD_CF_SIZE]; + __attribute__((aligned(SRSLTE_SIMD_BIT_ALIGN))) cf_t x1[SRSLTE_SIMD_CF_SIZE]; + + srslte_simd_cfi_store(x0, _x0); + srslte_simd_cfi_store(x1, _x1); + + cf_error0 = x0[1] - x0_gold[1]; + cf_error1 = x1[1] - x1_gold[1]; + error += crealf(cf_error0) * crealf(cf_error0) + cimagf(cf_error0) * cimagf(cf_error0) + + crealf(cf_error1) * crealf(cf_error1) + cimagf(cf_error1) * cimagf(cf_error1); + + return (error < 1e-3); +} + +#endif /* SRSLTE_SIMD_CF_SIZE != 0 */ + bool test_vec_dot_prod_ccc(void) { __attribute__((aligned(256))) cf_t a[14]; __attribute__((aligned(256))) cf_t b[14]; @@ -413,6 +505,10 @@ int main(int argc, char **argv) { #ifdef LV_HAVE_AVX RUN_TEST(test_zf_solver_avx); #endif /* LV_HAVE_AVX */ + +#if SRSLTE_SIMD_CF_SIZE != 0 + RUN_TEST(test_zf_solver_simd); +#endif /* SRSLTE_SIMD_CF_SIZE != 0*/ } if (mmse_solver) { @@ -426,6 +522,10 @@ int main(int argc, char **argv) { #ifdef LV_HAVE_AVX RUN_TEST(test_mmse_solver_avx); #endif /* LV_HAVE_AVX */ + +#if SRSLTE_SIMD_CF_SIZE != 0 + RUN_TEST(test_mmse_solver_simd); +#endif /* SRSLTE_SIMD_CF_SIZE != 0*/ } RUN_TEST(test_vec_dot_prod_ccc); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 9ccd21559..d3d836b21 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -104,6 +104,12 @@ void srslte_vec_lut_sss(const short *x, const unsigned short *lut, short *y, con srslte_vec_lut_sss_simd(x, lut, y, len); } +void srslte_vec_lut_sis(const short *x, const unsigned int *lut, short *y, const uint32_t len) { + for (int i=0; i < len; i++) { + y[lut[i]] = x[i]; + } +} + void *srslte_vec_malloc(uint32_t size) { void *ptr; if (posix_memalign(&ptr, SRSLTE_SIMD_BIT_ALIGN, size)) { @@ -421,8 +427,8 @@ void srslte_vec_quant_sus(const int16_t *in, uint16_t *out, const float gain, co } } -void srs_vec_cf_cpy(const cf_t *dst, cf_t *src, int len) { - srslte_vec_cp_simd(dst, src, len); +void srs_vec_cf_cpy(const cf_t *src, cf_t *dst, int len) { + srslte_vec_cp_simd(src, dst, len); } void srslte_vec_interleave(const cf_t *x, const cf_t *y, cf_t *z, const int len) { diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 7008790a3..7b53f7405 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -50,12 +50,14 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels) // Suppress radio stdout srslte_rf_suppress_stdout(&rf_device); - - tx_adv_auto = true; + + continuous_tx = false; + tx_adv_auto = true; // Set default preamble length each known device // We distinguish by device family, maybe we should calibrate per device if (strstr(srslte_rf_name(&rf_device), "uhd")) { burst_preamble_sec = uhd_default_burst_preamble_sec; + continuous_tx = true; } else if (strstr(srslte_rf_name(&rf_device), "bladerf")) { burst_preamble_sec = blade_default_burst_preamble_sec; } else { @@ -89,6 +91,7 @@ void radio::reset() printf("Resetting Radio...\n"); srslte_rf_stop_rx_stream(&rf_device); radio_is_streaming = false; + usleep(100000); } void radio::set_manual_calibration(rf_cal_t* calibration) @@ -110,6 +113,14 @@ void radio::set_burst_preamble(double preamble_us) burst_preamble_sec = (double) preamble_us/1e6; } +void radio::set_continuous_tx(bool enable) { + continuous_tx = enable; +} + +bool radio::is_continuous_tx() { + return continuous_tx; +} + void radio::set_tx_adv(int nsamples) { tx_adv_auto = false; @@ -175,7 +186,7 @@ float radio::set_tx_power(float power) float radio::get_max_tx_power() { - return 10; + return 40; } float radio::get_rssi() @@ -450,6 +461,10 @@ void radio::set_tx_srate(double srate) // Calculate TX advance in seconds from samples and sampling rate tx_adv_sec = nsamples/cur_tx_srate; + if (tx_adv_sec<0) { + tx_adv_sec *= -1; + tx_adv_negative = true; + } } void radio::register_error_handler(srslte_rf_error_handler_t h) diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index b9d41d3f2..2ae7515a7 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -60,8 +60,9 @@ void rlc_tm::empty_queue() // Drop all messages in TX queue byte_buffer_t *buf; while(ul_queue.size() > 0) { - ul_queue.read(&buf); - pool->deallocate(buf); + if (ul_queue.try_read(&buf)) { + pool->deallocate(buf); + } } } @@ -112,14 +113,18 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) return 0; } byte_buffer_t *buf; - ul_queue.read(&buf); - pdu_size = buf->N_bytes; - memcpy(payload, buf->msg, buf->N_bytes); - log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); - pool->deallocate(buf); - log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); - return pdu_size; + if (ul_queue.try_read(&buf)) { + pdu_size = buf->N_bytes; + memcpy(payload, buf->msg, buf->N_bytes); + log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", + rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); + pool->deallocate(buf); + log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); + return pdu_size; + } else { + log->warning("Queue empty while trying to read\n"); + return 0; + } } void rlc_tm::write_pdu(uint8_t *payload, uint32_t nof_bytes) diff --git a/srsenb/hdr/mac/scheduler_metric.h b/srsenb/hdr/mac/scheduler_metric.h index 11e77b455..4685f932a 100644 --- a/srsenb/hdr/mac/scheduler_metric.h +++ b/srsenb/hdr/mac/scheduler_metric.h @@ -42,18 +42,17 @@ private: bool new_allocation(uint32_t nof_rbg, uint32_t* rbgmask); void update_allocation(uint32_t new_mask); - bool allocation_is_valid(uint32_t mask); - - + bool allocation_is_valid(uint32_t mask); + dl_harq_proc* apply_user_allocation(sched_ue *user); + uint32_t get_required_rbg(sched_ue *user, uint32_t tti); uint32_t count_rbg(uint32_t mask); uint32_t calc_rbg_mask(bool mask[25]); bool used_rb[MAX_RBG]; - uint32_t nof_users_with_data; - - uint32_t current_tti; + + uint32_t current_tti; uint32_t total_rb; uint32_t used_rb_mask; uint32_t nof_ctrl_symbols; @@ -72,8 +71,8 @@ private: bool new_allocation(uint32_t L, ul_harq_proc::ul_alloc_t *alloc); bool allocation_is_valid(ul_harq_proc::ul_alloc_t alloc); + ul_harq_proc* apply_user_allocation(sched_ue *user); - uint32_t nof_users_with_data; bool used_rb[MAX_PRB]; uint32_t current_tti; diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 90db552a6..aaa4b49b7 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -40,7 +40,8 @@ class sched_ue { public: // used by sched_metric - uint32_t ue_idx; + dl_harq_proc* dl_next_alloc; + ul_harq_proc* ul_next_alloc; bool has_pucch; diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index e7fbd0c10..165c1ea3e 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -95,7 +95,7 @@ public: bool process_pdus(); uint8_t *request_buffer(uint32_t tti, uint32_t len); - void process_pdu(uint8_t *pdu, uint32_t nof_bytes, uint32_t tstamp); + void process_pdu(uint8_t *pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp); void push_pdu(uint32_t tti, uint32_t len); void deallocate_pdu(uint32_t tti); diff --git a/srsenb/hdr/upper/s1ap.h b/srsenb/hdr/upper/s1ap.h index 35369790f..35b871bdc 100644 --- a/srsenb/hdr/upper/s1ap.h +++ b/srsenb/hdr/upper/s1ap.h @@ -32,7 +32,6 @@ #include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" #include "srslte/common/common.h" -#include "srslte/common/msg_queue.h" #include "srslte/common/threads.h" #include "srslte/interfaces/enb_interfaces.h" #include "common_enb.h" diff --git a/srsenb/src/mac/scheduler_metric.cc b/srsenb/src/mac/scheduler_metric.cc index a15faebbd..f6ec18555 100644 --- a/srsenb/src/mac/scheduler_metric.cc +++ b/srsenb/src/mac/scheduler_metric.cc @@ -78,7 +78,6 @@ uint32_t dl_metric_rr::get_required_rbg(sched_ue *user, uint32_t tti) void dl_metric_rr::new_tti(std::map &ue_db, uint32_t start_rb, uint32_t nof_rb, uint32_t nof_ctrl_symbols_, uint32_t tti) { - total_rb = start_rb+nof_rb; for (uint32_t i=0;i &ue_db, uint32_t start_rb } available_rb = nof_rb; used_rb_mask = calc_rbg_mask(used_rb); - current_tti = tti; - nof_ctrl_symbols = nof_ctrl_symbols_; - - nof_users_with_data = 0; - for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { - sched_ue *user = (sched_ue*) &iter->second; - if (user->get_pending_dl_new_data(current_tti) || user->get_pending_dl_harq(current_tti)) { - user->ue_idx = nof_users_with_data; - nof_users_with_data++; + current_tti = tti; + nof_ctrl_symbols = nof_ctrl_symbols_; + + if(ue_db.size()==0) + return; + + // give priority in a time-domain RR basis + uint32_t priority_idx = current_tti % ue_db.size(); + std::map::iterator iter = ue_db.begin(); + std::advance(iter,priority_idx); + for(uint32_t ue_count = 0 ; ue_count < ue_db.size() ; ++iter, ++ue_count) { + if(iter==ue_db.end()) { + iter = ue_db.begin(); // wrap around } + sched_ue *user = (sched_ue*) &iter->second; + user->dl_next_alloc = apply_user_allocation(user); } } @@ -136,25 +141,11 @@ bool dl_metric_rr::allocation_is_valid(uint32_t mask) return (mask & used_rb_mask); } -dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) -{ - uint32_t pending_data = user->get_pending_dl_new_data(current_tti); +dl_harq_proc* dl_metric_rr::apply_user_allocation(sched_ue *user) { + uint32_t pending_data = user->get_pending_dl_new_data(current_tti); dl_harq_proc *h = user->get_pending_dl_harq(current_tti); - // Time-domain RR scheduling -#if ASYNC_DL_SCHED - if (pending_data || h) { -#else - if (pending_data || (h && !h->is_empty())) { -#endif - if (nof_users_with_data) { - if ((current_tti%nof_users_with_data) != user->ue_idx) { - return NULL; - } - } - } - - // Schedule retx if we have space + // Schedule retx if we have space #if ASYNC_DL_SCHED if (h) { #else @@ -164,38 +155,45 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) // If can schedule the same mask, do it if (!allocation_is_valid(retx_mask)) { update_allocation(retx_mask); - return h; + return h; } - // If not, try to find another mask in the current tti + + // If not, try to find another mask in the current tti uint32_t nof_rbg = count_rbg(retx_mask); if (nof_rbg < available_rb) { if (new_allocation(nof_rbg, &retx_mask)) { update_allocation(retx_mask); h->set_rbgmask(retx_mask); - return h; + return h; } } - } + } // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID #if ASYNC_DL_SCHED - h = user->get_empty_dl_harq(); + h = user->get_empty_dl_harq(); if (h) { #else - if (h && h->is_empty()) { + if (h && h->is_empty()) { #endif // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols); - uint32_t newtx_mask = 0; + uint32_t newtx_mask = 0; new_allocation(pending_rb, &newtx_mask); if (newtx_mask) { update_allocation(newtx_mask); h->set_rbgmask(newtx_mask); - return h; + return h; } - } + } } - return NULL; + + return NULL; +} + +dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) +{ + return user->dl_next_alloc; } @@ -219,15 +217,20 @@ void ul_metric_rr::new_tti(std::map &ue_db, uint32_t nof_rb_, available_rb = nof_rb_; bzero(used_rb, nof_rb*sizeof(bool)); - nof_users_with_data = 0; - for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { - sched_ue *user = (sched_ue*) &iter->second; - if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty(0)) { - user->ue_idx = nof_users_with_data; - nof_users_with_data++; - } - } + if(ue_db.size()==0) + return; + // give priority in a time-domain RR basis + uint32_t priority_idx = (current_tti+ue_db.size()/2) % ue_db.size(); // make DL and UL interleaved + std::map::iterator iter = ue_db.begin(); + std::advance(iter,priority_idx); + for(uint32_t ue_count = 0 ; ue_count < ue_db.size() ; ++iter, ++ue_count) { + if(iter==ue_db.end()) { + iter = ue_db.begin(); // wrap around + } + sched_ue *user = (sched_ue*) &iter->second; + user->ul_next_alloc = apply_user_allocation(user); + } } bool ul_metric_rr::allocation_is_valid(ul_harq_proc::ul_alloc_t alloc) @@ -288,56 +291,49 @@ void ul_metric_rr::update_allocation(ul_harq_proc::ul_alloc_t alloc) available_rb -= alloc.L; } -ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) -{ +ul_harq_proc* ul_metric_rr::apply_user_allocation(sched_ue *user) { // Time-domain RR scheduling - uint32_t pending_data = user->get_pending_ul_new_data(current_tti); + uint32_t pending_data = user->get_pending_ul_new_data(current_tti); ul_harq_proc *h = user->get_ul_harq(current_tti); - - if (pending_data || !h->is_empty(0)) { - if (nof_users_with_data) { - if ((current_tti%nof_users_with_data) != user->ue_idx) { - return NULL; - } - } - } - // Schedule retx if we have space - + // Schedule retx if we have space if (!h->is_empty(0)) { - ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); - + // If can schedule the same mask, do it if (allocation_is_valid(alloc)) { update_allocation(alloc); return h; } - + // If not, try to find another mask in the current tti if (new_allocation(alloc.L, &alloc)) { update_allocation(alloc); h->set_alloc(alloc); return h; } - } - // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID + } + + // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID if (h->is_empty(0)) { - // Allocate resources based on pending data + // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_ul(pending_data); - ul_harq_proc::ul_alloc_t alloc; + ul_harq_proc::ul_alloc_t alloc; new_allocation(pending_rb, &alloc); if (alloc.L) { update_allocation(alloc); h->set_alloc(alloc); - return h; + return h; } - } + } } - return NULL; + return NULL; } - +ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) +{ + return user->ul_next_alloc; +} } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 6cb4462e8..f9245ac9b 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -49,7 +49,7 @@ namespace srsenb { * *******************************************************/ -sched_ue::sched_ue() : ue_idx(0), has_pucch(false), power_headroom(0), rnti(0), max_mcs_dl(0), max_mcs_ul(0), +sched_ue::sched_ue() : dl_next_alloc(NULL), ul_next_alloc(NULL), has_pucch(false), power_headroom(0), rnti(0), max_mcs_dl(0), max_mcs_ul(0), fixed_mcs_ul(0), fixed_mcs_dl(0), phy_config_dedicated_enabled(false) { log_h = NULL; diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index 39e8c88e2..975d6e9b1 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -142,7 +142,7 @@ void ue::set_tti(uint32_t tti) { #include -void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, uint32_t tstamp) +void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp) { // Unpack ULSCH MAC PDU mac_msg_ul.init_rx(nof_bytes, true); diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index f47656c6d..a18df9a59 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -121,7 +121,7 @@ uint32_t rrc::generate_sibs() // msg is array of SI messages, each SI message msg[i] may contain multiple SIBs // all SIBs in a SI message msg[i] share the same periodicity - LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *msg = (LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT*)calloc(nof_messages, sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT)); + LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *msg = (LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT*)calloc(nof_messages+1, sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT)); // Copy SIB1 to first SI message msg[0].N_sibs = 1; @@ -1090,9 +1090,13 @@ void rrc::ue::notify_s1ap_ue_ctxt_setup_complete() void rrc::ue::notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e) { LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT res; + res.ext=false; res.E_RABSetupListBearerSURes.len = 0; res.E_RABFailedToSetupListBearerSURes.len = 0; + res.CriticalityDiagnostics_present = false; + res.E_RABFailedToSetupListBearerSURes_present = false; + for(uint32_t i=0; ilen; i++) { res.E_RABSetupListBearerSURes_present = true; LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT *erab = &e->buffer[i]; @@ -1447,6 +1451,8 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu) // Get DRB1 configuration if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0], 1)) { parent->rrc_log->error("Getting DRB1 configuration\n"); + printf("The QCI %d for DRB1 is invalid or not configured.\n", erabs[5].qos_params.qCI.QCI); + return; } else { conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size = 1; } @@ -1524,8 +1530,10 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1) // Get DRB configuration - if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid)) { - parent->rrc_log->error("Getting DRB configuration\n"); + if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid-2)) { + parent->rrc_log->error("Getting DRB configuration\n"); + printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[lcid+4].qos_params.qCI.QCI); + return; } else { conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size++; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 687ced63b..32964daff 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -1806,7 +1806,7 @@ s1ap_nas_transport::pack_attach_accept(ue_emm_ctx_t *ue_emm_ctx, ue_ecm_ctx_t *u act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check //set apn - act_def_eps_bearer_context_req.apn.apn = m_s1ap->m_s1ap_args.mme_apn; + strncpy(act_def_eps_bearer_context_req.apn.apn, m_s1ap->m_s1ap_args.mme_apn.c_str(), LIBLTE_STRING_LEN); act_def_eps_bearer_context_req.proc_transaction_id = ue_emm_ctx->procedure_transaction_id; //FIXME //Set DNS server @@ -1933,10 +1933,10 @@ s1ap_nas_transport::pack_emm_information( ue_ctx_t *ue_ctx, srslte::byte_buffer_ LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; emm_info.full_net_name_present = true; - emm_info.full_net_name.name = std::string("Software Radio Systems LTE"); + strncpy(emm_info.full_net_name.name, "Software Radio Systems LTE", LIBLTE_STRING_LEN); emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.short_net_name_present = true; - emm_info.short_net_name.name = std::string("srsLTE"); + strncpy(emm_info.short_net_name.name, "srsLTE", LIBLTE_STRING_LEN); emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.local_time_zone_present = false; diff --git a/srsue/hdr/mac/demux.h b/srsue/hdr/mac/demux.h index c738a0fd3..410865c55 100644 --- a/srsue/hdr/mac/demux.h +++ b/srsue/hdr/mac/demux.h @@ -51,12 +51,13 @@ public: 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_mch(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); bool get_uecrid_successful(); - - void process_pdu(uint8_t *pdu, uint32_t nof_bytes, uint32_t tstamp); + + void process_pdu(uint8_t *pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp); private: const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index 7b119c27b..4f5014532 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -50,7 +50,7 @@ class mac ,public mac_interface_rrc ,public srslte::timer_callback ,public srslte::mac_interface_timers - ,public thread + ,public periodic_thread { public: mac(); @@ -68,15 +68,13 @@ public: void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid); void bch_decoded_ok(uint8_t *payload, uint32_t len); void pch_decoded_ok(uint32_t len); - void tti_clock(uint32_t tti); /******** Interface from RLC (RLC -> MAC) ****************/ void bcch_start_rx(); - void bcch_stop_rx(); void bcch_start_rx(int si_window_start, int si_window_length); void pcch_start_rx(); - void pcch_stop_rx(); + void clear_rntis(); void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD); void reconfiguration(); void reset(); @@ -110,15 +108,14 @@ public: private: - void run_thread(); + void run_period(); static const int MAC_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD static const int MAC_PDU_THREAD_PRIO = DEFAULT_PRIORITY-5; static const int MAC_NOF_HARQ_PROC = 2*HARQ_DELAY_MS; // Interaction with PHY - srslte::tti_sync_cv ttisync; - phy_interface_mac *phy_h; + phy_interface_mac *phy_h; rlc_interface_mac *rlc_h; rrc_interface_mac *rrc_h; srslte::log *log_h; @@ -130,11 +127,7 @@ private: ue_rnti_t uernti; uint32_t tti; - bool started; - bool is_synchronized; - uint16_t last_temporal_crnti; - uint16_t phy_rnti; - + /* Multiplexing/Demultiplexing Units */ mux mux_unit; demux demux_unit; @@ -168,19 +161,6 @@ private: mac_metrics_t metrics; - /* Class to run Timers in a dedicated thread */ - class mac_timers : public periodic_thread { - public: - void init(srslte::timers *timers, srslte::log *log_h); - private: - void run_period(); - srslte::timers *timers; - bool running; - srslte::log *log_h; - }; - - mac_timers mactimers; - /* Class to process MAC PDUs from DEMUX unit */ class pdu_process : public thread { public: diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index c9a1cd6a1..b036f3869 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -27,9 +27,6 @@ #ifndef SRSUE_PHCH_COMMON_H #define SRSUE_PHCH_COMMON_H -#define TX_MODE_CONTINUOUS 1 - - #include #include #include @@ -68,15 +65,17 @@ public: float cur_radio_power; float cur_pusch_power; float avg_rsrp; + float avg_rsrp_cqi; float avg_rsrp_dbm; + float avg_rsrp_sync_dbm; float avg_rsrq_db; float avg_rssi_dbm; float last_radio_rssi; float rx_gain_offset; - float avg_snr_db; + float avg_snr_db_cqi; + float avg_snr_db_sync; float avg_noise; - bool pcell_meas_enabled; uint32_t pcell_report_period; // Save last TBS for mcs>28 cases diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index f18f52833..78559d3cd 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -28,6 +28,7 @@ #define SRSUE_PHCH_RECV_H #include +#include #include "srslte/srslte.h" #include "srslte/common/log.h" @@ -50,29 +51,23 @@ class phch_recv : public thread, public chest_feedback_itf public: phch_recv(); ~phch_recv(); + void init(srslte::radio_multi* radio_handler, mac_interface_phy *mac,rrc_interface_phy *rrc, prach *prach_buffer, srslte::thread_pool *_workers_pool, phch_common *_worker_com, srslte::log* _log_h, srslte::log *_log_phy_lib_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1); void stop(); - void set_agc_enable(bool enable); + void radio_overflow(); - void set_earfcn(std::vector earfcn); - void force_freq(float dl_freq, float ul_freq); - - void reset_sync(); - void cell_search_start(); - void cell_search_next(bool reset = false); - void cell_select(uint32_t earfcn, srslte_cell_t cell); - bool cell_handover(srslte_cell_t cell); + // RRC interface for controling the SYNC state + phy_interface_rrc::cell_search_ret_t cell_search(phy_interface_rrc::phy_cell_t *cell); + bool cell_select(phy_interface_rrc::phy_cell_t *cell); + bool cell_is_camping(); + // RRC interface for controlling the neighbour cell measurement void meas_reset(); int meas_start(uint32_t earfcn, int pci); int meas_stop(uint32_t earfcn, int pci); - uint32_t get_current_tti(); - - bool status_is_sync(); - // from chest_feedback_itf void in_sync(); void out_of_sync(); @@ -80,37 +75,21 @@ public: void set_time_adv_sec(float time_adv_sec); void get_current_cell(srslte_cell_t *cell, uint32_t *earfcn = NULL); + uint32_t get_current_tti(); + // From UE configuration + void set_agc_enable(bool enable); + void set_earfcn(std::vector earfcn); + void force_freq(float dl_freq, float ul_freq); + // Other functions const static int MUTEX_X_WORKER = 4; - double set_rx_gain(double gain); int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); int scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); private: - std::vector earfcn; - - void reset(); - void radio_error(); - void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo); - void run_thread(); - - void set_sampling_rate(); - bool set_frequency(); - bool set_cell(); - - void cell_search_inc(); - void cell_reselect(); - - float get_cfo(); - - uint32_t new_earfcn; - srslte_cell_t new_cell; - - bool running; - // Class to run cell search class search { public: @@ -119,9 +98,7 @@ private: ~search(); void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, phch_recv *parent); void reset(); - float get_last_gain(); float get_last_cfo(); - void set_N_id_2(int N_id_2); void set_agc_enable(bool enable); ret_code run(srslte_cell_t *cell); @@ -137,22 +114,23 @@ private: // Class to synchronize system frame number class sfn_sync { public: - typedef enum {IDLE, SFN_FOUND, SFX0_FOUND, ERROR, TIMEOUT} ret_code; + typedef enum {IDLE, SFN_FOUND, SFX0_FOUND, SFN_NOFOUND, ERROR} ret_code; ~sfn_sync(); - void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout = SYNC_SFN_TIMEOUT); + void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_subframes = SFN_SYNC_NOF_SUBFRAMES); void reset(); bool set_cell(srslte_cell_t cell); ret_code run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt, bool sfidx_only = false); private: + const static int SFN_SYNC_NOF_SUBFRAMES = 100; + + uint32_t cnt; + uint32_t timeout; srslte::log *log_h; srslte_ue_sync_t *ue_sync; cf_t *buffer[SRSLTE_MAX_PORTS]; srslte_ue_mib_t ue_mib; - uint32_t cnt; - uint32_t timeout; - const static uint32_t SYNC_SFN_TIMEOUT = 80; }; // Class to perform cell measurements @@ -170,7 +148,7 @@ private: void set_cell(srslte_cell_t cell); ret_code run_subframe(uint32_t sf_idx); ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx); - ret_code run_multiple_subframes(cf_t *buffer, int offset, uint32_t sf_idx, uint32_t nof_sf); + ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf); float rssi(); float rsrp(); float rsrq(); @@ -261,9 +239,26 @@ private: // 36.133 9.1.2.1 for band 7 const static float ABSOLUTE_RSRP_THRESHOLD_DBM = -125; + std::vector earfcn; + + void reset(); + void radio_error(); + void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo); + void run_thread(); + float get_tx_cfo(); + + void set_sampling_rate(); + bool set_frequency(); + bool set_cell(); + + uint32_t new_earfcn; + srslte_cell_t new_cell; + + bool radio_is_overflow; + bool radio_overflow_return; + bool running; // Objects for internal use - measure measure_p; search search_p; sfn_sync sfn_p; intra_measure intra_freq_meas; @@ -298,19 +293,128 @@ private: const static uint32_t NOF_OUT_OF_SYNC_SF = 200; const static uint32_t NOF_IN_SYNC_SF = 100; - // State for primary cell - typedef enum { - IDLE = 0, - CELL_SEARCH, - CELL_SELECT, - CELL_RESELECT, - CELL_MEASURE, - CELL_CAMP, - } phy_state_t; + // State machine for SYNC thread + class sync_state { + public: + typedef enum { + IDLE = 0, + CELL_SEARCH, + SFN_SYNC, + CAMPING, + } state_t; - phy_state_t phy_state, prev_state; + /* Run_state is called by the main thread at the start of each loop. It updates the state + * and returns the current state + */ + state_t run_state() { + pthread_mutex_lock(&inside); + cur_state = next_state; + pthread_cond_broadcast(&cvar); + pthread_mutex_unlock(&inside); + return cur_state; + } - bool is_in_idle; + // Called by the main thread at the end of each state to indicate it has finished. + void state_exit(bool exit_ok = true) { + pthread_mutex_lock(&inside); + if (cur_state == SFN_SYNC && exit_ok == true) { + next_state = CAMPING; + } else { + next_state = IDLE; + } + pthread_mutex_unlock(&inside); + } + void force_sfn_sync() { + pthread_mutex_lock(&inside); + next_state = SFN_SYNC; + pthread_mutex_unlock(&inside); + } + + /* Functions to be called from outside the STM thread to instruct the STM to switch state. + * The functions change the state and wait until it has changed it. + * + * These functions are mutexed and only 1 can be called at a time + */ + void go_idle() { + pthread_mutex_lock(&outside); + go_state(IDLE); + pthread_mutex_unlock(&outside); + } + void run_cell_search() { + pthread_mutex_lock(&outside); + go_state(CELL_SEARCH); + wait_state_change(CELL_SEARCH); + pthread_mutex_unlock(&outside); + } + void run_sfn_sync() { + pthread_mutex_lock(&outside); + go_state(SFN_SYNC); + wait_state_change(SFN_SYNC); + pthread_mutex_unlock(&outside); + } + + + /* Helpers below this */ + bool is_idle() { + return cur_state == IDLE; + } + bool is_camping() { + return cur_state == CAMPING; + } + + const char *to_string() { + switch(cur_state) { + case IDLE: + return "IDLE"; + case CELL_SEARCH: + return "SEARCH"; + case SFN_SYNC: + return "SYNC"; + case CAMPING: + return "CAMPING"; + default: + return "UNKNOWN"; + } + } + + sync_state() { + pthread_mutex_init(&inside, NULL); + pthread_mutex_init(&outside, NULL); + pthread_cond_init(&cvar, NULL); + cur_state = IDLE; + next_state = IDLE; + } + private: + + void go_state(state_t s) { + pthread_mutex_lock(&inside); + next_state = s; + while(cur_state != s) { + pthread_cond_wait(&cvar, &inside); + } + pthread_mutex_unlock(&inside); + } + + /* Waits until there is a call to set_state() and then run_state(). Returns when run_state() returns */ + void wait_state_change(state_t prev_state) { + pthread_mutex_lock(&inside); + while(cur_state == prev_state) { + pthread_cond_wait(&cvar, &inside); + } + pthread_mutex_unlock(&inside); + } + + state_t cur_state, next_state; + pthread_mutex_t inside, outside; + pthread_cond_t cvar; + + }; + + pthread_mutex_t rrc_mutex; + + sync_state phy_state; + + search::ret_code cell_search_ret; // Sampling rate mode (find is 1.96 MHz, camp is the full cell BW) enum { @@ -320,9 +424,8 @@ private: // This is the primary cell srslte_cell_t cell; - bool cell_is_set; bool started; - float time_adv_sec; + float time_adv_sec, next_time_adv_sec; uint32_t tti; bool do_agc; @@ -330,8 +433,8 @@ private: uint32_t tx_mutex_cnt; float ul_dl_factor; - uint32_t current_earfcn; - int cur_earfcn_index; + int current_earfcn; + uint32_t cellsearch_earfcn_index; float dl_freq; float ul_freq; diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 53848905b..14687da73 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -53,6 +53,7 @@ public: cf_t* get_buffer(uint32_t antenna_idx); void set_tti(uint32_t tti, uint32_t tx_tti); void set_tx_time(srslte_timestamp_t tx_time, uint32_t next_offset); + void set_prach(cf_t *prach_ptr, float prach_power); void set_cfo(float cfo); void set_ul_params(bool pregen_disabled = false); @@ -169,6 +170,8 @@ private: bool sr_configured; float cfo; bool rar_cqi_request; + cf_t *prach_ptr; + float prach_power; uint32_t rssi_read_cnt; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 828a6b7e1..a1a7c2a66 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -82,21 +82,18 @@ public: /********** RRC INTERFACE ********************/ void reset(); - void sync_reset(); void configure_ul_params(bool pregen_disabled = false); - void cell_search_start(); - void cell_search_next(); - void cell_select(uint32_t earfcn, srslte_cell_t phy_cell); - bool cell_handover(srslte_cell_t cell); + cell_search_ret_t cell_search(phy_cell_t *cell); + bool cell_select(phy_cell_t *cell); void meas_reset(); int meas_start(uint32_t earfcn, int pci); int meas_stop(uint32_t earfcn, int pci); - /********** MAC INTERFACE ********************/ - /* Functions to synchronize with a cell */ - bool sync_status(); // this is also RRC interface + // also MAC interface + bool cell_is_camping(); + /********** MAC INTERFACE ********************/ /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ void set_crnti(uint16_t rnti); diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 651203eb7..06d8f61cf 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -58,13 +58,11 @@ namespace srsue { bool is_ready_to_send(uint32_t current_tti); bool is_pending(); int tx_tti(); - - void send(srslte::radio* radio_handler, float cfo, float pathloss, srslte_timestamp_t rx_time); - float get_p0_preamble(); - - static const uint32_t tx_advance_sf = 4; // Number of subframes to advance transmission - - private: + cf_t* generate(float cfo, uint32_t *nof_sf, float *target_power = NULL); + + private: + + const static int MAX_LEN_SF = 3; LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config; phy_args_t *args; @@ -81,7 +79,7 @@ namespace srsue { srslte_cell_t cell; cf_t *signal_buffer; srslte_cfo_t cfo_h; - float target_power_dbm; + float target_power_dbm; }; diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index f66ac9fba..a305df931 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -69,6 +69,8 @@ public: bool init(all_args_t *args_); void stop(); + bool attach(); + bool deattach(); bool is_attached(); void start_plot(); diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 802b7880d..63bb19533 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -64,6 +64,7 @@ typedef struct { std::string device_args; std::string time_adv_nsamples; std::string burst_preamble; + std::string continuous_tx; }rf_args_t; typedef struct { @@ -112,6 +113,7 @@ typedef struct { phy_args_t phy; float metrics_period_secs; bool pregenerate_signals; + bool print_buffer_state; bool metrics_csv_enable; std::string metrics_csv_filename; }expert_args_t; @@ -155,6 +157,8 @@ public: virtual bool init(all_args_t *args_) = 0; virtual void stop() = 0; + virtual bool attach() = 0; + virtual bool deattach() = 0; virtual bool is_attached() = 0; virtual void start_plot() = 0; diff --git a/srsue/hdr/upper/gw.h b/srsue/hdr/upper/gw.h index 10ab50e56..3b17eb75b 100644 --- a/srsue/hdr/upper/gw.h +++ b/srsue/hdr/upper/gw.h @@ -30,7 +30,6 @@ #include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" #include "srslte/common/common.h" -#include "srslte/common/msg_queue.h" #include "srslte/common/interfaces_common.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/threads.h" diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 5f431cc0a..ee9838dd4 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -43,29 +43,20 @@ namespace srsue { typedef enum { EMM_STATE_NULL = 0, EMM_STATE_DEREGISTERED, - EMM_STATE_REGISTERED_INITIATED, EMM_STATE_REGISTERED, - EMM_STATE_SERVICE_REQUEST_INITIATED, EMM_STATE_DEREGISTERED_INITIATED, EMM_STATE_TAU_INITIATED, EMM_STATE_N_ITEMS, } emm_state_t; static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"NULL", "DEREGISTERED", - "REGISTERED INITIATED", "REGISTERED", - "SERVICE REQUEST INITIATED", "DEREGISTERED INITIATED", "TRACKING AREA UPDATE INITIATED"}; static const bool eia_caps[8] = {false, true, true, false, false, false, false, false}; static const bool eea_caps[8] = {true, true, true, false, false, false, false, false}; -typedef enum { - PLMN_NOT_SELECTED = 0, - PLMN_SELECTED -} plmn_selection_state_t; - class nas : public nas_interface_rrc, public nas_interface_ue, @@ -83,20 +74,16 @@ public: emm_state_t get_state(); // RRC interface - void notify_connection_setup(); + void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy); + void set_barring(barring_t barring); void write_pdu(uint32_t lcid, byte_buffer_t *pdu); uint32_t get_ul_count(); bool is_attached(); - bool is_attaching(); - bool is_data_requested(); - bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi); bool get_k_asme(uint8_t *k_asme_, uint32_t n); - bool plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code); - void plmn_search_end(); // UE interface - void attach_request(); - void deattach_request(); + bool attach_request(); + bool deattach_request(); // PCAP void start_pcap(srslte::nas_pcap *pcap_); @@ -112,9 +99,10 @@ private: emm_state_t state; - plmn_selection_state_t plmn_selection; + nas_interface_rrc::barring_t current_barring; + + bool plmn_is_selected; LIBLTE_RRC_PLMN_IDENTITY_STRUCT current_plmn; - LIBLTE_RRC_PLMN_IDENTITY_STRUCT selecting_plmn; LIBLTE_RRC_PLMN_IDENTITY_STRUCT home_plmn; std::vector known_plmns; @@ -148,6 +136,10 @@ private: // PCAP srslte::nas_pcap *pcap = NULL; + bool running; + + bool rrc_connect(); + void integrity_generate(uint8_t *key_128, uint32_t count, uint8_t direction, @@ -160,6 +152,8 @@ private: bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps); + void select_plmn(); + // Parsers void parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu); void parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu); @@ -171,10 +165,12 @@ private: void parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu); void parse_emm_information(uint32_t lcid, byte_buffer_t *pdu); + // Packet generators + void gen_attach_request(byte_buffer_t *msg); + void gen_service_request(byte_buffer_t *msg); + // Senders - void send_attach_request(); void send_identity_response(); - void send_service_request(); void send_esm_information_response(); void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg); void send_security_mode_reject(uint8_t cause); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index ba8fdd046..fb89fbbe9 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -36,6 +36,7 @@ #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/security.h" #include "srslte/common/threads.h" +#include "srslte/common/block_queue.h" #include #include @@ -52,21 +53,21 @@ using srslte::byte_buffer_t; namespace srsue { - class cell_t { public: bool is_valid() { - return earfcn != 0 && srslte_cell_isvalid(&phy_cell); + return phy_cell.earfcn != 0 && srslte_cell_isvalid(&phy_cell.cell); } bool equals(cell_t *x) { - return equals(x->earfcn, x->phy_cell.id); + return equals(x->phy_cell.earfcn, x->phy_cell.cell.id); } bool equals(uint32_t earfcn, uint32_t pci) { - return earfcn == this->earfcn && pci == phy_cell.id; + return earfcn == this->phy_cell.earfcn && pci == phy_cell.cell.id; } + // NaN means an RSRP value has not yet been obtained. Keep then in the list and clean them if never updated bool greater(cell_t *x) { - return rsrp > x->rsrp; + return rsrp > x->rsrp || isnan(rsrp); } bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { if (has_valid_sib1) { @@ -78,11 +79,39 @@ class cell_t } return false; } - cell_t() { - srslte_cell_t tmp = {}; - cell_t(tmp, 0, 0); + + uint32_t nof_plmns() { + if (has_valid_sib1) { + return sib1.N_plmn_ids; + } else { + return 0; + } } - cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) { + + LIBLTE_RRC_PLMN_IDENTITY_STRUCT get_plmn(uint32_t idx) { + if (idx < sib1.N_plmn_ids && has_valid_sib1) { + return sib1.plmn_id[idx].id; + } else { + LIBLTE_RRC_PLMN_IDENTITY_STRUCT null; + null.mnc = 0; + null.mcc = 0; + return null; + } + } + + uint16_t get_tac() { + if (has_valid_sib1) { + return sib1.tracking_area_code; + } else { + return 0; + } + } + + cell_t() { + phy_interface_rrc::phy_cell_t tmp = {}; + cell_t(tmp, 0); + } + cell_t(phy_interface_rrc::phy_cell_t phy_cell, float rsrp) { gettimeofday(&last_update, NULL); this->has_valid_sib1 = false; this->has_valid_sib2 = false; @@ -90,7 +119,6 @@ class cell_t this->has_valid_sib13 = false; this->phy_cell = phy_cell; this->rsrp = rsrp; - this->earfcn = earfcn; in_sync = true; bzero(&sib1, sizeof(sib1)); bzero(&sib2, sizeof(sib2)); @@ -99,15 +127,15 @@ class cell_t } uint32_t get_earfcn() { - return earfcn; + return phy_cell.earfcn; } uint32_t get_pci() { - return phy_cell.id; + return phy_cell.cell.id; } void set_rsrp(float rsrp) { - if (~isnan(rsrp)) { + if (!isnan(rsrp)) { this->rsrp = rsrp; } in_sync = true; @@ -170,6 +198,20 @@ class cell_t return has_valid_sib13; } + bool has_sib(uint32_t index) { + switch(index) { + case 0: + return has_sib1(); + case 1: + return has_sib2(); + case 2: + return has_sib3(); + case 12: + return has_sib13(); + } + return false; + } + uint16_t get_mcc() { if (has_valid_sib1) { if (sib1.N_plmn_ids > 0) { @@ -188,12 +230,11 @@ class cell_t return 0; } - srslte_cell_t phy_cell; + phy_interface_rrc::phy_cell_t phy_cell; bool in_sync; private: float rsrp; - uint32_t earfcn; struct timeval last_update; bool has_valid_sib1; @@ -231,56 +272,61 @@ public: void stop(); rrc_state_t get_state(); - void set_args(rrc_args_t *args); // Timeout callback interface void timer_expired(uint32_t timeout_id); - void liblte_rrc_log(char *str); - // NAS interface void write_sdu(uint32_t lcid, byte_buffer_t *sdu); - - uint16_t get_mcc(); - - uint16_t get_mnc(); - void enable_capabilities(); - void plmn_search(); - void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request); + uint16_t get_mcc(); + uint16_t get_mnc(); + int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]); + void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); + bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, + srslte::byte_buffer_t *dedicatedInfoNAS); + void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi); // PHY interface void in_sync(); void out_of_sync(); - void earfcn_end(); - void cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci); // MAC interface void ho_ra_completed(bool ra_successful); void release_pucch_srs(); void run_tti(uint32_t tti); - void ra_problem(); // GW interface - bool is_connected(); - + bool is_connected(); // this is also NAS interface bool have_drb(); // PDCP interface void write_pdu(uint32_t lcid, byte_buffer_t *pdu); - void write_pdu_bcch_bch(byte_buffer_t *pdu); - void write_pdu_bcch_dlsch(byte_buffer_t *pdu); - void write_pdu_pcch(byte_buffer_t *pdu); private: + + typedef struct { + enum { + PCCH, + STOP + } command; + byte_buffer_t *pdu; + } cmd_msg_t; + + bool running; + srslte::block_queue cmd_q; + void run_thread(); + + void process_pcch(byte_buffer_t *pdu); + srslte::byte_buffer_pool *pool; srslte::log *rrc_log; phy_interface_rrc *phy; @@ -295,6 +341,8 @@ private: LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; + byte_buffer_t *dedicatedInfoNAS; + byte_buffer_t* byte_align_and_pack(); void send_ul_ccch_msg(); void send_ul_dcch_msg(); @@ -304,28 +352,22 @@ private: rrc_state_t state; uint8_t transaction_id; + LIBLTE_RRC_S_TMSI_STRUCT ueIdentity; + bool ueIdentity_configured; + bool drb_up; rrc_args_t args; - bool first_stimsi_attempt; + + uint32_t cell_clean_cnt; uint16_t ho_src_rnti; cell_t ho_src_cell; - uint32_t ho_target_pci; - bool ho_syncing; - phy_interface_rrc::phy_cfg_t ho_src_phy_cfg; - mac_interface_rrc::mac_cfg_t ho_src_mac_cfg; + phy_interface_rrc::phy_cfg_t previous_phy_cfg; + mac_interface_rrc::mac_cfg_t previous_mac_cfg; bool pending_mob_reconf; LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf; - // timeouts in ms - - uint32_t connecting_timeout; - static const uint32_t RRC_CONNECTING_TIMEOUT = 5000; - - uint32_t plmn_select_timeout; - static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 10000; - uint8_t k_rrc_enc[32]; uint8_t k_rrc_int[32]; uint8_t k_up_enc[32]; @@ -341,7 +383,7 @@ private: srslte::mac_interface_timers *mac_timers; uint32_t n310_cnt, N310; uint32_t n311_cnt, N311; - uint32_t t300, t301, t310, t311, t304; + uint32_t t300, t301, t302, t310, t311, t304; // Radio bearers typedef enum{ @@ -376,42 +418,35 @@ private: std::vector neighbour_cells; cell_t *serving_cell; void set_serving_cell(uint32_t cell_idx); - void set_serving_cell(uint32_t earfcn, uint32_t pci); + void set_serving_cell(phy_interface_rrc::phy_cell_t phy_cell); int find_neighbour_cell(uint32_t earfcn, uint32_t pci); bool add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp); - bool add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); + bool add_neighbour_cell(phy_interface_rrc::phy_cell_t phy_cell, float rsrp); bool add_neighbour_cell(cell_t *cell); void sort_neighbour_cells(); void clean_neighbours(); std::vector::iterator delete_neighbour(std::vector::iterator it); void delete_neighbour(uint32_t cell_idx); - typedef enum { - SI_ACQUIRE_IDLE = 0, - SI_ACQUIRE_SIB1, - SI_ACQUIRE_SIB2 - } si_acquire_state_t; + bool configure_serving_cell(); - si_acquire_state_t si_acquire_state; - void run_si_acquisition_procedure(); + bool si_acquire(uint32_t index); uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf); - uint32_t nof_sib1_trials; - uint16_t sysinfo_index; - uint32_t last_win_start; + const static int SIB_SEARCH_TIMEOUT_MS = 1000; - bool select_next_cell_in_plmn(); - LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id; + const static uint32_t NOF_REQUIRED_SIBS = 3; // SIB1, SIB2 and SIB3 - bool thread_running; - void run_thread(); + bool initiated; + bool ho_start; + bool go_idle; // Measurements sub-class class rrc_meas { public: void init(rrc *parent); void reset(); - void parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_config); + bool parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_config); void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti); void run_tti(uint32_t tti); bool timer_expired(uint32_t timer_id); @@ -500,6 +535,18 @@ private: rrc_meas measurements; + // Measurement object from phy + typedef struct { + float rsrp; + float rsrq; + uint32_t tti; + uint32_t earfcn; + uint32_t pci; + } phy_meas_t; + + void process_phy_meas(); + void process_new_phy_meas(phy_meas_t meas); + std::queue phy_meas_q; // Cell selection/reselection functions/variables typedef struct { @@ -510,25 +557,36 @@ private: float s_intrasearchP; float q_hyst; float threshservinglow; - } cell_resel_cfg_t; cell_resel_cfg_t cell_resel_cfg; float get_srxlev(float Qrxlevmeas); float get_squal(float Qqualmeas); - void cell_reselection_eval(float rsrp, float rsrq); - bool cell_selection_eval(float rsrp, float rsrq = 0); - bool connection_requested; - void plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); + typedef enum { + CHANGED_CELL = 0, + SAME_CELL = 1, + NO_CELL = 2 + } cs_ret_t; + + cs_ret_t cell_selection(); + bool cell_selection_criteria(float rsrp, float rsrq = 0); + void cell_reselection(float rsrp, float rsrq); + + phy_interface_rrc::cell_search_ret_t cell_search(); + + LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id; + bool plmn_is_selected; + + bool security_is_activated; // RLC interface void max_retx_attempted(); // Senders - void send_con_request(); - void send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint16_t crnti); + void send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause); + void send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause); void send_con_restablish_complete(); void send_con_setup_complete(byte_buffer_t *nas_msg); void send_ul_info_transfer(byte_buffer_t *nas_msg); @@ -542,16 +600,15 @@ private: void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu); // Helpers - void ho_failed(); + bool con_reconfig(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig); + void con_reconfig_failed(); + bool con_reconfig_ho(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig); bool ho_prepare(); - void ho_synced(uint32_t target_pci); + void ho_failed(); void rrc_connection_release(); - void con_restablish_cell_reselected(); void radio_link_failure(); void leave_connected(); - static void* start_sib_thread(void *rrc_); - void sib_search(); void apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); void apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); void handle_sib1(); @@ -566,7 +623,7 @@ private: void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg); void add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg); void release_drb(uint8_t lcid); - void apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg); + bool apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg); void apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults); void apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cfg, bool apply_defaults); diff --git a/srsue/hdr/upper/rrc_common.h b/srsue/hdr/upper/rrc_common.h index 912f39ddc..f79a98bed 100644 --- a/srsue/hdr/upper/rrc_common.h +++ b/srsue/hdr/upper/rrc_common.h @@ -33,27 +33,11 @@ namespace srsue { // RRC states (3GPP 36.331 v10.0.0) typedef enum { RRC_STATE_IDLE = 0, - RRC_STATE_PLMN_START, - RRC_STATE_PLMN_SELECTION, - RRC_STATE_CELL_SELECTING, - RRC_STATE_CELL_SELECTED, - RRC_STATE_CONNECTING, RRC_STATE_CONNECTED, - RRC_STATE_HO_PREPARE, - RRC_STATE_HO_PROCESS, - RRC_STATE_LEAVE_CONNECTED, RRC_STATE_N_ITEMS, } rrc_state_t; static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", - "PLMN SELECTED", - "PLMN SELECTION", - "CELL SELECTING", - "CELL SELECTED", - "CONNECTING", - "CONNECTED", - "HO PREPARE", - "HO PROCESS", - "LEAVE CONNECTED"}; + "CONNECTED"}; } // namespace srsue diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 3e0d2f44f..640b78bd5 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -107,27 +107,29 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes) Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n"); - pdus.push(buff, nof_bytes); + pdus.push(buff, nof_bytes, srslte::pdu_queue::DCH); } else { Warning("Trying to push PDU with payload size zero\n"); } } -/* Demultiplexing of logical channels and dissassemble of MAC CE - * This function enqueues the packet and returns quicly because ACK - * deadline is important here. - */ +/* Demultiplexing of logical channels and dissassemble of MAC CE + * This function enqueues the packet and returns quickly because ACK + * deadline is important here. + */ void demux::push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { - return pdus.push(buff, nof_bytes, tstamp); + return pdus.push(buff, nof_bytes, srslte::pdu_queue::DCH, 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); + pdus.push(buff, nof_bytes, srslte::pdu_queue::BCH, tstamp); +} + +void demux::push_pdu_mch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { + pdus.push(buff, nof_bytes, srslte::pdu_queue::MCH, tstamp); } bool demux::process_pdus() @@ -135,15 +137,25 @@ bool demux::process_pdus() return pdus.process_pdus(); } -void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes, uint32_t tstamp) +void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp) { - // Unpack DLSCH MAC PDU - mac_msg.init_rx(nof_bytes); - mac_msg.parse_packet(mac_pdu); + Debug("Processing MAC PDU channel %d\n", channel); + switch(channel) { + case srslte::pdu_queue::DCH: + // Unpack DLSCH MAC PDU + mac_msg.init_rx(nof_bytes); + mac_msg.parse_packet(mac_pdu); - process_sch_pdu(&mac_msg); - //srslte_vec_fprint_byte(stdout, mac_pdu, nof_bytes); - Debug("MAC PDU processed\n"); + process_sch_pdu(&mac_msg); + //srslte_vec_fprint_byte(stdout, mac_pdu, nof_bytes); + break; + case srslte::pdu_queue::BCH: + rlc->write_pdu_bcch_dlsch(mac_pdu, nof_bytes); + break; + case srslte::pdu_queue::MCH: + // Process downlink MCH + break; + } } void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg) diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 4033df888..14f895257 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -41,27 +41,21 @@ namespace srsue { -mac::mac() : ttisync(10240), - timers(64), +mac::mac() : timers(64), mux_unit(MAC_NOF_HARQ_PROC), pdu_process_thread(&demux_unit) { - started = false; pcap = NULL; bzero(&metrics, sizeof(mac_metrics_t)); } bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac *rrc, srslte::log *log_h_) { - started = false; phy_h = phy; rlc_h = rlc; rrc_h = rrc; log_h = log_h_; tti = 0; - is_synchronized = false; - last_temporal_crnti = 0; - phy_rnti = 0; srslte_softbuffer_rx_init(&pch_softbuffer, 100); @@ -79,23 +73,18 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac reset(); - started = true; - start(MAC_MAIN_THREAD_PRIO); + start_periodic(1000, MAC_MAIN_THREAD_PRIO); - mactimers.init(&timers, log_h); - - return started; + return true; } void mac::stop() { srslte_softbuffer_rx_free(&pch_softbuffer); - started = false; - ttisync.increase(); pdu_process_thread.stop(); + stop_thread(); wait_thread_finish(); - mactimers.stop(); } void mac::start_pcap(srslte::mac_pcap* pcap_) @@ -150,59 +139,38 @@ void mac::reset() bzero(&uernti, sizeof(ue_rnti_t)); } -void mac::mac_timers::init(srslte::timers *timers, srslte::log *log_h) { - this->timers = timers; - running = true; - this->log_h = log_h; - start_periodic(1000); -} +void mac::run_period() { -void mac::mac_timers::run_period() { - timers->step_all(); -} + /* Warning: Here order of invocation of procedures is important!! */ -void mac::run_thread() { - int cnt=0; + tti = phy_h->get_current_tti(); - while (!phy_h->sync_status() && started) { - usleep(5000); - if (phy_h->sync_status()) { - Debug("Setting ttysync to %d\n", phy_h->get_current_tti()); - ttisync.set_producer_cntr(phy_h->get_current_tti()); - } + log_h->step(tti); + + // Step all procedures + bsr_procedure.step(tti); + phr_procedure.step(tti); + + // Check if BSR procedure need to start SR + + if (bsr_procedure.need_to_send_sr(tti)) { + Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", tti); + sr_procedure.start(); + } + if (bsr_procedure.need_to_reset_sr()) { + Debug("Resetting SR procedure by BSR request\n"); + sr_procedure.reset(); + } + sr_procedure.step(tti); + + // Check SR if we need to start RA + if (sr_procedure.need_random_access()) { + ra_procedure.start_mac_order(); } - while(started) { - - /* Warning: Here order of invocation of procedures is important!! */ - tti = ttisync.wait(); - - log_h->step(tti); - - // Step all procedures - bsr_procedure.step(tti); - phr_procedure.step(tti); - - // Check if BSR procedure need to start SR - - if (bsr_procedure.need_to_send_sr(tti)) { - Debug("Starting SR procedure by BSR request, PHY TTI=%d\n", tti); - sr_procedure.start(); - } - if (bsr_procedure.need_to_reset_sr()) { - Debug("Resetting SR procedure by BSR request\n"); - sr_procedure.reset(); - } - sr_procedure.step(tti); - - // Check SR if we need to start RA - if (sr_procedure.need_random_access()) { - ra_procedure.start_mac_order(); - } - ra_procedure.step(tti); - - rrc_h->run_tti(tti); - } + ra_procedure.step(tti); + timers.step_all(); + rrc_h->run_tti(tti); } void mac::bcch_start_rx() @@ -221,28 +189,17 @@ void mac::bcch_start_rx(int si_window_start, int si_window_length) Info("SCHED: Searching for DL grant for SI-RNTI window_st=%d, window_len=%d\n", si_window_start, si_window_length); } -void mac::bcch_stop_rx() -{ - phy_h->pdcch_dl_search_reset(); -} - void mac::pcch_start_rx() { phy_h->pdcch_dl_search(SRSLTE_RNTI_PCH, SRSLTE_PRNTI); Info("SCHED: Searching for DL grant for P-RNTI\n"); } -void mac::pcch_stop_rx() +void mac::clear_rntis() { phy_h->pdcch_dl_search_reset(); } - -void mac::tti_clock(uint32_t tti) -{ - ttisync.increase(tti); -} - void mac::bch_decoded_ok(uint8_t* payload, uint32_t len) { // Send MIB to RLC diff --git a/srsue/src/main.cc b/srsue/src/main.cc index a30892cc7..d8469f3ae 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -77,6 +77,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("rf.time_adv_nsamples", bpo::value(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance") ("rf.burst_preamble_us", bpo::value(&args->rf.burst_preamble)->default_value("auto"), "Transmission time advance") + ("rf.continuous_tx", bpo::value(&args->rf.continuous_tx)->default_value("auto"), "Transmit samples continuously to the radio or on bursts (auto/yes/no). Default is auto (yes for UHD, no for rest)") ("rrc.feature_group", bpo::value(&args->rrc.feature_group)->default_value(0xe6041c00), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041c00") @@ -159,6 +160,10 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.pregenerate_signals)->default_value(false), "Pregenerate uplink signals after attach. Improves CPU performance.") + ("expert.print_buffer_state", + bpo::value(&args->expert.print_buffer_state)->default_value(false), + "Prints on the console the buffer state every 10 seconds") + ("expert.rssi_sensor_enabled", bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(false), "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") @@ -261,18 +266,22 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.average_subframe_enabled)->default_value(true), "Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.") - ("expert.time_correct_period", - bpo::value(&args->expert.phy.time_correct_period)->default_value(5), - "Period for sampling time offset correction.") + ("expert.estimator_fil_auto", + bpo::value(&args->expert.phy.estimator_fil_auto)->default_value(false), + "The channel estimator smooths the channel estimate with an adaptative filter.") + + ("expert.estimator_fil_stddev", + bpo::value(&args->expert.phy.estimator_fil_stddev)->default_value(1.0f), + "Sets the channel estimator smooth gaussian filter standard deviation.") + + ("expert.estimator_fil_order", + bpo::value(&args->expert.phy.estimator_fil_order)->default_value(4), + "Sets the channel estimator smooth gaussian filter order (even values perform better).") ("expert.sss_algorithm", bpo::value(&args->expert.phy.sss_algorithm)->default_value("full"), "Selects the SSS estimation algorithm.") - ("expert.estimator_fil_w", - bpo::value(&args->expert.phy.estimator_fil_w)->default_value(0.1), - "Chooses the coefficients for the 3-tap channel estimator centered filter.") - ("expert.pdsch_csi_enabled", bpo::value(&args->expert.phy.pdsch_csi_enabled)->default_value(false), "Stores the Channel State Information and uses it for weightening the softbits. It is only compatible with TM1.") @@ -470,18 +479,25 @@ int main(int argc, char *argv[]) pthread_t input; pthread_create(&input, NULL, &input_loop, &args); - bool plot_started = false; - bool signals_pregenerated = false; - + printf("Attaching UE...\n"); + while (!ue->attach() && running) { + sleep(1); + } + if (running) { + if (args.expert.pregenerate_signals) { + ue->pregenerate_signals(true); + } + if (args.gui.enable) { + ue->start_plot(); + } + } + int cnt=0; while (running) { - if (ue->is_attached()) { - if (!signals_pregenerated && args.expert.pregenerate_signals) { - ue->pregenerate_signals(true); - signals_pregenerated = true; - } - if (!plot_started && args.gui.enable) { - ue->start_plot(); - plot_started = true; + if (args.expert.print_buffer_state) { + cnt++; + if (cnt==10) { + cnt=0; + ue->print_pool(); } } sleep(1); diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 13cca2ec8..120f2ee51 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -248,7 +248,7 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable, radio_h->tx_single(buffer, nof_samples, tx_time); is_first_of_burst = false; } else { - if (TX_MODE_CONTINUOUS) { + if (radio_h->is_continuous_tx()) { if (!is_first_of_burst) { radio_h->tx_single(zeros, nof_samples, tx_time); } @@ -342,11 +342,13 @@ void phch_common::reset() { cur_radio_power = 0; sr_last_tx_tti = -1; cur_pusch_power = 0; + avg_snr_db_cqi = 0; + avg_snr_db_sync = 0; avg_rsrp = 0; + avg_rsrp_cqi = 0; avg_rsrp_dbm = 0; avg_rsrq_db = 0; - pcell_meas_enabled = false; pcell_report_period = 20; bzero(pending_ack, sizeof(pending_ack_t)*TTIMOD_SZ); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 01e63cecd..3bb6f4a40 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -26,6 +26,8 @@ #include #include +#include +#include #include "srslte/srslte.h" #include "srslte/common/log.h" #include "srsue/hdr/phy/phch_worker.h" @@ -90,12 +92,11 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma // Initialize SFN synchronizer sfn_p.init(&ue_sync, sf_buffer, log_h); - // Initialize measurement class for the primary cell - measure_p.init(sf_buffer, log_h, nof_rx_antennas); - // Start intra-frequency measurement intra_freq_meas.init(worker_com, rrc, log_h); + pthread_mutex_init(&rrc_mutex, NULL); + reset(); running = true; // Start main thread @@ -112,6 +113,7 @@ phch_recv::~phch_recv() { free(sf_buffer[i]); } } + pthread_mutex_destroy(&rrc_mutex); srslte_ue_sync_free(&ue_sync); } @@ -124,30 +126,486 @@ void phch_recv::stop() void phch_recv::reset() { + radio_is_overflow = false; + radio_overflow_return = false; in_sync_cnt = 0; out_of_sync_cnt = 0; tx_mutex_cnt = 0; - phy_state = IDLE; time_adv_sec = 0; next_offset = 0; - cell_is_set = false; srate_mode = SRATE_NONE; - current_earfcn = 0; + current_earfcn = -1; sfn_p.reset(); - measure_p.reset(); search_p.reset(); + phy_state.go_idle(); } + + + + + + +/** + * Higher layers API. + * + * These functions are called by higher layers (RRC) to control the Cell search and cell selection procedures. + * They manipulate the SYNC state machine to switch states and perform different actions. In order to ensure mutual + * exclusion any change of state variables such as cell configuration, MIB decoder, etc. must be done while the + * SYNC thread is in IDLE. + * + * Functions will manipulate the SYNC state machine (sync_state class) to jump to states and wait for result then + * return the result to the higher layers. + * + * Cell Search: + * It's the process of searching for cells in the bands or set of EARFCNs supported by the UE. Cell search is performed + * at 1.92 MHz sampling rate and involves PSS/SSS synchronization (PCI extraction) and MIB decoding for number of Ports and PRB. + * + * + * Cell Select: + * It's the process of moving the cell state from IDLE->CAMPING or from CAMPING->IDLE->CAMPING when RRC indicates to + * select a different cell. + * + * If it is a new cell, the reconfiguration must take place while sync_state is on IDLE. + * + * cell_search() and cell_select() functions can not be called concurrently. A mutex is used to prevent it from happening. + * + */ + + +/* A call to cell_search() finds the strongest cell in the set of supported EARFCNs. When the first cell is found, + * returns 1 and stores cell information and RSRP values in the pointers (if provided). If a cell is not found in the current + * frequency it moves to the next one and the next call to cell_search() will look in the next EARFCN in the set. + * If no cells are found in any frequency it returns 0. If error returns -1. + */ + +phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::phy_cell_t *found_cell) +{ + phy_interface_rrc::cell_search_ret_t ret; + + ret.found = phy_interface_rrc::cell_search_ret_t::ERROR; + ret.last_freq = phy_interface_rrc::cell_search_ret_t::NO_MORE_FREQS; + + pthread_mutex_lock(&rrc_mutex); + + // Move state to IDLE + Info("Cell Search: Start EARFCN index=%u/%lu\n", cellsearch_earfcn_index, earfcn.size()); + phy_state.go_idle(); + + if (current_earfcn != (int) earfcn[cellsearch_earfcn_index]) { + current_earfcn = (int) earfcn[cellsearch_earfcn_index]; + Info("Cell Search: changing frequency to EARFCN=%d\n", current_earfcn); + set_frequency(); + } + + // Move to CELL SEARCH and wait to finish + Info("Cell Search: Setting Cell search state\n"); + phy_state.run_cell_search(); + + // Check return state + switch(cell_search_ret) { + case search::CELL_FOUND: + // If a cell is found, configure it, synchronize and measure it + if (set_cell()) { + + Info("Cell Search: Setting sampling rate and synchronizing SFN...\n"); + set_sampling_rate(); + phy_state.run_sfn_sync(); + + if (phy_state.is_camping()) { + log_h->info("Cell Search: Sync OK. Camping on cell PCI=%d\n", cell.id); + if (found_cell) { + found_cell->earfcn = current_earfcn; + found_cell->cell = cell; + } + ret.found = phy_interface_rrc::cell_search_ret_t::CELL_FOUND; + } else { + log_h->info("Cell Search: Could not synchronize with cell\n"); + ret.found = phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND; + } + } else { + Error("Cell Search: Setting cell PCI=%d, nof_prb=%d\n", cell.id, cell.nof_prb); + } + break; + case search::CELL_NOT_FOUND: + Info("Cell Search: No cell found in this frequency\n"); + ret.found = phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND; + break; + default: + Error("Cell Search: while receiving samples\n"); + radio_error(); + break; + } + + cellsearch_earfcn_index++; + if (cellsearch_earfcn_index >= earfcn.size()) { + Info("Cell Search: No more frequencies in the current EARFCN set\n"); + cellsearch_earfcn_index = 0; + ret.last_freq = phy_interface_rrc::cell_search_ret_t::NO_MORE_FREQS; + } else { + ret.last_freq = phy_interface_rrc::cell_search_ret_t::MORE_FREQS; + } + + pthread_mutex_unlock(&rrc_mutex); + return ret; +} + +/* Cell select synchronizes to a new cell (e.g. during HO or during cell reselection on IDLE) or + * re-synchronizes with the current cell if cell argument is NULL + */ +bool phch_recv::cell_select(phy_interface_rrc::phy_cell_t *new_cell) { + pthread_mutex_lock(&rrc_mutex); + + bool ret = false; + int cnt = 0; + + // Move state to IDLE + if (!new_cell) { + Info("Cell Select: Starting cell resynchronization\n"); + } else { + if (!srslte_cell_isvalid(&cell)) { + log_h->error("Cell Select: Invalid cell. ID=%d, PRB=%d, ports=%d\n", cell.id, cell.nof_prb, cell.nof_ports); + goto unlock; + } + Info("Cell Select: Starting cell selection for PCI=%d, EARFCN=%d\n", new_cell->cell.id, new_cell->earfcn); + } + + // Wait for any pending PHICH + while(worker_com->is_any_pending_ack() && cnt < 10) { + usleep(1000); + cnt++; + Info("Cell Select: waiting pending PHICH (cnt=%d)\n", cnt); + } + + Info("Cell Select: Going to IDLE\n"); + phy_state.go_idle(); + + /* Reset everything */ + for(uint32_t i=0;iget_nof_workers();i++) { + ((phch_worker*) workers_pool->get_worker(i))->reset(); + } + + worker_com->reset(); + sfn_p.reset(); + search_p.reset(); + srslte_ue_sync_reset(&ue_sync); + + /* Reconfigure cell if necessary */ + if (new_cell) { + if (new_cell->cell.id != cell.id) { + Info("Cell Select: Reconfiguring cell\n"); + cell = new_cell->cell; + if (!set_cell()) { + Error("Cell Select: Reconfiguring cell\n"); + goto unlock; + } + } + + /* Select new frequency if necessary */ + if ((int) new_cell->earfcn != current_earfcn) { + Info("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); + if (set_frequency()) { + Error("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); + goto unlock; + } + current_earfcn = new_cell->earfcn; + } + } + + /* Change sampling rate if necessary */ + if (srate_mode != SRATE_CAMP) { + set_sampling_rate(); + log_h->info("Cell Select: Setting CAMPING sampling rate\n"); + } + + /* SFN synchronization */ + phy_state.run_sfn_sync(); + if (phy_state.is_camping()) { + Info("Cell Select: SFN synchronized. CAMPING...\n"); + ret = true; + } else { + Info("Cell Select: Could not synchronize SFN\n"); + } + +unlock: + pthread_mutex_unlock(&rrc_mutex); + return ret; +} + +bool phch_recv::cell_is_camping() { + return phy_state.is_camping(); +} + + + + +/** + * MAIN THREAD + * + * The main thread process the SYNC state machine. Every state except IDLE must have exclusive access to + * all variables. If any change of cell configuration must be done, the thread must be in IDLE. + * + * On each state except campling, 1 function is called and the thread jumps to the next state based on the output. + * + * It has 3 states: Cell search, SFN syncrhonization, intial measurement and camping. + * - CELL_SEARCH: Initial Cell id and MIB acquisition. Uses 1.92 MHz sampling rate + * - CELL_SYNC: Full sampling rate, uses MIB to obtain SFN. When SFN is obtained, moves to CELL_CAMP + * - CELL_CAMP: Cell camping state. Calls the PHCH workers to process subframes and mantains cell synchronization. + * - IDLE: Receives and discards received samples. Does not mantain synchronization. + * + */ + +void phch_recv::run_thread() +{ + phch_worker *worker = NULL; + phch_worker *last_worker = NULL; + cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; + uint32_t sf_idx = 0; + + bool is_end_of_burst = false; + + cf_t *dummy_buffer[SRSLTE_MAX_PORTS]; + + for (int i=0;istep(tti); + + sf_idx = tti%10; + + switch (phy_state.run_state()) { + case sync_state::CELL_SEARCH: + /* Search for a cell in the current frequency and go to IDLE. + * The function search_p.run() will not return until the search finishes + */ + cell_search_ret = search_p.run(&cell); + phy_state.state_exit(); + break; + case sync_state::SFN_SYNC: + /* SFN synchronization using MIB. run_subframe() receives and processes 1 subframe + * and returns + */ + switch(sfn_p.run_subframe(&cell, &tti)) { + case sfn_sync::SFN_FOUND: + phy_state.state_exit(); + break; + case sfn_sync::IDLE: + break; + default: + phy_state.state_exit(false); + break; + } + break; + case sync_state::CAMPING: + + worker = (phch_worker *) workers_pool->wait_worker(tti); + if (worker) { + for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) { + buffer[i] = worker->get_buffer(i); + } + + switch(srslte_ue_sync_zerocopy_multi(&ue_sync, buffer)) { + case 1: + + if (last_worker) { + Debug("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz, snr_sf=%.2f dB, rsrp=%.2f dB, noise=%.2f dB\n", + srslte_ue_sync_get_cfo(&ue_sync), + 15000*last_worker->get_ref_cfo(), + 15000*ue_sync.strack.cfo_pss_mean, + last_worker->get_snr(), last_worker->get_rsrp(), last_worker->get_noise()); + } + + last_worker = worker; + + Debug("SYNC: Worker %d synchronized\n", worker->get_id()); + + metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); + metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync); + worker_com->set_sync_metrics(metrics); + + // Check if we need to TX a PRACH + if (prach_buffer->is_ready_to_send(tti)) { + prach_ptr = prach_buffer->generate(get_tx_cfo(), &prach_nof_sf, &prach_power); + if (!prach_ptr) { + Error("Generating PRACH\n"); + } + } + + /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ + srslte_timestamp_t rx_time, tx_time; + srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); + srslte_timestamp_copy(&tx_time, &rx_time); + if (prach_ptr) { + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3); + } else { + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); + } + + worker->set_prach(prach_ptr?&prach_ptr[prach_sf_cnt*SRSLTE_SF_LEN_PRB(cell.nof_prb)]:NULL, prach_power); + worker->set_cfo(get_tx_cfo()); + worker->set_tti(tti, tx_mutex_cnt); + worker->set_tx_time(tx_time, next_offset); + next_offset = 0; + if (next_time_adv_sec != time_adv_sec) { + time_adv_sec = next_time_adv_sec; + } + tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; + + // Advance/reset prach subframe pointer + if (prach_ptr) { + prach_sf_cnt++; + if (prach_sf_cnt == prach_nof_sf) { + prach_sf_cnt = 0; + prach_ptr = NULL; + } + } + + is_end_of_burst = true; + + // Start worker + workers_pool->start_worker(worker); + + // Save signal for Intra-frequency measurement + if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) { + srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]); + } + if (srslte_cell_isvalid(&cell)) { + intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); + } + break; + case 0: + Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); + out_of_sync(); + worker->release(); + worker_com->reset_ul(); + break; + default: + radio_error(); + break; + } + } else { + // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here + running = false; + } + break; + case sync_state::IDLE: + if (radio_h->is_init()) { + uint32_t nsamples = 1920; + if (current_srate > 0) { + nsamples = current_srate/1000; + } + Debug("Discarting %d samples\n", nsamples); + if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) { + printf("SYNC: Receiving from radio while in IDLE_RX\n"); + } + if (is_end_of_burst) { + radio_h->tx_end(); + is_end_of_burst = true; + } + } else { + usleep(1000); + } + break; + } + + /* Radio overflow detected. If CAMPING, go through SFN sync again and when + * SFN is found again go back to camping + */ + if (!pthread_mutex_trylock(&rrc_mutex)) { + if (radio_is_overflow) { + // If we are coming back from an overflow + if (radio_overflow_return) { + if (phy_state.is_camping()) { + log_h->info("Successfully resynchronized after overflow. Returning to CAMPING\n"); + radio_overflow_return = false; + radio_is_overflow = false; + } else if (phy_state.is_idle()) { + log_h->warning("Could not synchronize SFN after radio overflow. Trying again\n"); + rrc->out_of_sync(); + phy_state.force_sfn_sync(); + } + } else { + // Overflow has occurred now while camping + if (phy_state.is_camping()) { + log_h->warning("Detected radio overflow while camping. Resynchronizing cell\n"); + sfn_p.reset(); + phy_state.force_sfn_sync(); + radio_overflow_return = true; + } else { + radio_is_overflow = false; + } + // If overflow occurs in any other state, it does not harm + } + } + pthread_mutex_unlock(&rrc_mutex); + } + + // Increase TTI counter + tti = (tti+1) % 10240; + } +} + + + + + + + + + + + + +/*************** + * + * Utility functions called by the main thread or by functions called by other threads + * + */ +void phch_recv::radio_overflow() { + radio_is_overflow = true; +} + void phch_recv::radio_error() { log_h->error("SYNC: Receiving from radio.\n"); - reset(); - phy_state = CELL_SEARCH; // Need to find a method to effectively reset radio, reloading the driver does not work radio_h->reset(); } +void phch_recv::in_sync() { + in_sync_cnt++; + // Send RRC in-sync signal after 100 ms consecutive subframes + if (in_sync_cnt == NOF_IN_SYNC_SF) { + rrc->in_sync(); + in_sync_cnt = 0; + out_of_sync_cnt = 0; + } +} + +// Out of sync called by worker or phch_recv every 1 or 5 ms +void phch_recv::out_of_sync() { + // Send RRC out-of-sync signal after 200 ms consecutive subframes + Info("Out-of-sync %d/%d\n", out_of_sync_cnt, NOF_OUT_OF_SYNC_SF); + out_of_sync_cnt++; + if (out_of_sync_cnt == NOF_OUT_OF_SYNC_SF) { + Info("Sending to RRC\n"); + rrc->out_of_sync(); + out_of_sync_cnt = 0; + in_sync_cnt = 0; + } +} + void phch_recv::set_cfo(float cfo) { srslte_ue_sync_set_cfo_ref(&ue_sync, cfo); } @@ -169,7 +627,31 @@ void phch_recv::set_agc_enable(bool enable) void phch_recv::set_time_adv_sec(float time_adv_sec) { - this->time_adv_sec = time_adv_sec; + // If transmitting earlier, transmit less samples to align time advance. If transmit later just delay next TX + if (time_adv_sec > this->time_adv_sec) { + next_offset = floor((this->time_adv_sec-time_adv_sec)*srslte_sampling_freq_hz(cell.nof_prb)+1); + } + this->next_time_adv_sec = time_adv_sec; + Info("Applying time_adv_sec=%.1f us, next_offset=%d\n", time_adv_sec*1e6, next_offset); +} + +float phch_recv::get_tx_cfo() +{ + float cfo = srslte_ue_sync_get_cfo(&ue_sync); + + float ret = cfo*ul_dl_factor; + + if (worker_com->args->cfo_is_doppler) { + ret *= -1; + } + + if (radio_h->get_freq_offset() != 0.0f) { + /* Compensates the radio frequency offset applied equally to DL and UL */ + const float offset_hz = (float) radio_h->get_freq_offset() * (1.0f - ul_dl_factor); + ret = cfo - offset_hz; + } + + return ret/15000; } void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) @@ -196,11 +678,6 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) srslte_sync_set_cfo_cp_enable(&q->sfind, false, 0); } - int time_correct_period = worker_com->args->time_correct_period; - if (time_correct_period > 0) { - srslte_ue_sync_set_sample_offset_correct_period(q, time_correct_period); - } - sss_alg_t sss_alg = SSS_FULL; if (!worker_com->args->sss_algorithm.compare("diff")) { sss_alg = SSS_DIFF; @@ -216,14 +693,17 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) } bool phch_recv::set_cell() { - cell_is_set = false; + + if (!phy_state.is_idle()) { + Warning("Can not change Cell while not in IDLE\n"); + return false; + } // Set cell in all objects if (srslte_ue_sync_set_cell(&ue_sync, cell)) { Error("SYNC: Setting cell: initiating ue_sync\n"); return false; } - measure_p.set_cell(cell); sfn_p.set_cell(cell); worker_com->set_cell(cell); intra_freq_meas.set_primay_cell(current_earfcn, cell); @@ -241,9 +721,7 @@ bool phch_recv::set_cell() { // Reset ue_sync and set CFO/gain from search procedure srslte_ue_sync_reset(&ue_sync); - cell_is_set = true; - - return cell_is_set; + return true; } void phch_recv::set_earfcn(std::vector earfcn) { @@ -255,143 +733,6 @@ void phch_recv::force_freq(float dl_freq, float ul_freq) { this->ul_freq = ul_freq; } -void phch_recv::reset_sync() { - - Info("SYNC: Reset. Going to Cell Select\n"); - sfn_p.reset(); - search_p.reset(); - measure_p.reset(); - srslte_ue_sync_reset(&ue_sync); - phy_state = CELL_SELECT; -} - -void phch_recv::cell_search_inc() -{ - cur_earfcn_index++; - if (cur_earfcn_index >= 0) { - if (cur_earfcn_index >= (int) earfcn.size()) { - Info("SYNC: Cell Search finished. Going to IDLE\n"); - cur_earfcn_index = 0; - phy_state = IDLE; - rrc->earfcn_end(); - } else { - Info("SYNC: Cell Search idx %d/%zu\n", cur_earfcn_index, earfcn.size()); - if (current_earfcn != earfcn[cur_earfcn_index]) { - current_earfcn = earfcn[cur_earfcn_index]; - set_frequency(); - } - phy_state = CELL_SEARCH; - } - } -} - -void phch_recv::cell_search_next(bool reset) { - if (reset) { - cur_earfcn_index = -1; - } - cell_search_inc(); -} - -void phch_recv::cell_search_start() { - if (phy_state == CELL_CAMP) { - Warning("SYNC: Can't start cell search procedure while camping on cell\n"); - } else { - if (earfcn.size() > 0) { - Info("SYNC: Starting Cell Search procedure in %zu EARFCNs...\n", earfcn.size()); - cell_search_next(true); - } else { - Info("SYNC: Empty EARFCN list. Stopping cell search...\n"); - log_h->console("Empty EARFCN list. Stopping cell search...\n"); - } - } -} - -bool phch_recv::cell_handover(srslte_cell_t cell) -{ - if (!srslte_cell_isvalid(&cell)) { - log_h->error("Received HO command to invalid cell. ID=%d, PRB=%d, ports=%d\n", cell.id, cell.nof_prb, cell.nof_ports); - return false; - } - - int cnt = 0; - while(worker_com->is_any_pending_ack() && cnt < 10) { - usleep(1000); - cnt++; - log_h->info("Cell HO: Waiting pending PHICH\n"); - } - - bool ret = false; - this->cell = cell; - Info("Cell HO: Stopping sync with current cell\n"); - phy_state = IDLE; - cnt = 0; - while(!is_in_idle && cnt<20) { - usleep(1000); - cnt++; - } - for(uint32_t i=0;iget_nof_workers();i++) { - ((phch_worker*) workers_pool->get_worker(i))->reset(); - } - worker_com->reset(); - if (is_in_idle) { - Info("Cell HO: Reconfiguring cell\n"); - if (set_cell()) { - Info("Cell HO: Synchronizing with new cell\n"); - phy_state = CELL_SELECT; - ret = true; - } else { - log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id); - ret = false; - } - } else { - log_h->error("Cell HO: Could not stop sync\n"); - ret = false; - } - return ret; -} - -/* interface from higher layers to select a new cell */ -void phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) -{ - Info("SYNC: Cell Reselect to EARFCN=%d, PCI=%d\n", earfcn, cell.id); - new_earfcn = earfcn; - new_cell = cell; - phy_state = CELL_RESELECT; -} - -/* Perform cell (re)-selection on IDLE or CAMP */ -void phch_recv::cell_reselect() -{ - uint32_t earfcn = new_earfcn; - srslte_cell_t cell = new_cell; - - reset_sync(); - - // If we are already in the new cell, just resynchronize - if (earfcn == current_earfcn && this->cell.id == cell.id) { - log_h->info("Cell Select: Already in cell EARFCN=%d, PCI=%d\n", earfcn, cell.id); - if (srate_mode != SRATE_CAMP) { - set_sampling_rate(); - log_h->info("Cell Select: Setting Camping sampling rate\n"); - } - } else { - - if (earfcn != current_earfcn) { - if (set_frequency()) { - log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); - } - current_earfcn = earfcn; - } - - this->cell = cell; - log_h->info("Cell Select: Configuring cell...\n"); - - if (set_cell()) { - log_h->info("Cell Select: Synchronizing on cell...\n"); - } - } -} - bool phch_recv::set_frequency() { double set_dl_freq = 0; @@ -409,7 +750,7 @@ bool phch_recv::set_frequency() current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); log_h->console("Searching cell in DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", - current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); + current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); radio_h->set_rx_freq(set_dl_freq); radio_h->set_tx_freq(set_ul_freq); @@ -424,25 +765,6 @@ bool phch_recv::set_frequency() } } -float phch_recv::get_cfo() -{ - float cfo = srslte_ue_sync_get_cfo(&ue_sync); - - float ret = cfo*ul_dl_factor; - - if (worker_com->args->cfo_is_doppler) { - ret *= -1; - } - - if (radio_h->get_freq_offset() != 0.0f) { - /* Compensates the radio frequency offset applied equally to DL and UL */ - const float offset_hz = (float) radio_h->get_freq_offset() * (1.0f - ul_dl_factor); - ret = cfo - offset_hz; - } - - return ret/15000; -} - void phch_recv::set_sampling_rate() { current_srate = (float) srslte_sampling_freq_hz(cell.nof_prb); @@ -457,11 +779,11 @@ void phch_recv::set_sampling_rate() radio_h->set_master_clock_rate(23.04e6); } #else - if (current_srate < 10e6) { - radio_h->set_master_clock_rate(4 * current_srate); - } else { - radio_h->set_master_clock_rate(current_srate); - } + if (current_srate < 10e6) { + radio_h->set_master_clock_rate(4 * current_srate); + } else { + radio_h->set_master_clock_rate(current_srate); + } #endif srate_mode = SRATE_CAMP; @@ -476,10 +798,6 @@ uint32_t phch_recv::get_current_tti() { return tti; } -bool phch_recv::status_is_sync() { - return phy_state == CELL_CAMP; -} - void phch_recv::get_current_cell(srslte_cell_t *cell_, uint32_t *earfcn) { if (cell_) { memcpy(cell_, &cell, sizeof(srslte_cell_t)); @@ -514,255 +832,6 @@ double phch_recv::set_rx_gain(double gain) { -/** - * MAIN THREAD - */ - -void phch_recv::run_thread() -{ - phch_worker *worker = NULL; - phch_worker *last_worker = NULL; - cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; - uint32_t sf_idx = 0; - phy_state = IDLE; - is_in_idle = true; - - cf_t *dummy_buffer[SRSLTE_MAX_PORTS]; - - for (int i=0;istep(tti); - log_phy_lib_h->step(tti); - - sf_idx = tti%10; - - prev_state = phy_state; - - switch (phy_state) { - case CELL_SEARCH: - switch(search_p.run(&cell)) - { - case search::CELL_FOUND: - if (!srslte_cell_isvalid(&cell)) { - Error("SYNC: Detected invalid cell. Going to IDLE\n"); - phy_state = IDLE; - break; - } - if (set_cell()) { - Info("SYNC: Setting sampling rate and going to Cell Select\n"); - set_sampling_rate(); - phy_state = CELL_SELECT; - } - break; - case search::CELL_NOT_FOUND: - cell_search_inc(); - break; - default: - radio_error(); - break; - } - break; - case CELL_RESELECT: - cell_reselect(); - break; - case CELL_SELECT: - switch (sfn_p.run_subframe(&cell, &tti)) - { - case sfn_sync::SFN_FOUND: - if (prev_state != CELL_SEARCH) { - log_h->info("Sync OK. Camping on cell PCI=%d...\n", cell.id); - phy_state = CELL_CAMP; - rrc->cell_camping(earfcn[cur_earfcn_index], cell); - } else { - log_h->info("Sync OK. Measuring PCI=%d...\n", cell.id); - measure_p.reset(); - phy_state = CELL_MEASURE; - } - break; - case sfn_sync::TIMEOUT: - log_h->warning("SYNC: Timeout while synchronizing SFN\n"); - rrc->out_of_sync(); - break; - case sfn_sync::IDLE: - break; - default: - radio_error(); - break; - } - break; - case CELL_MEASURE: - - switch(measure_p.run_subframe_sync(&ue_sync, sf_idx)) - { - case measure::MEASURE_OK: - - // Calibrate measure object since worker not yet calibrated - if (worker_com->args->rssi_sensor_enabled) { - measure_p.set_rx_gain_offset(measure_p.rssi() - radio_h->get_rssi() + 30); - } else { - measure_p.set_rx_gain_offset(worker_com->args->rx_gain_offset + radio_h->get_rx_gain()); - } - - log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id); - phy_state = CELL_CAMP; - rrc->cell_camping(earfcn[cur_earfcn_index], cell, measure_p.rsrp()); - break; - case measure::IDLE: - break; - default: - radio_error(); - break; - } - break; - case CELL_CAMP: - - worker = (phch_worker *) workers_pool->wait_worker(tti); - if (worker) { - for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) { - buffer[i] = worker->get_buffer(i); - } - - switch(srslte_ue_sync_zerocopy_multi(&ue_sync, buffer)) { - case 1: - - if (last_worker) { - Debug("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz, snr_sf=%.2f dB, rsrp=%.2f dB, noise=%.2f dB\n", - srslte_ue_sync_get_cfo(&ue_sync), - 15000*last_worker->get_ref_cfo(), - 15000*ue_sync.strack.cfo_pss_mean, - last_worker->get_snr(), last_worker->get_rsrp(), last_worker->get_noise()); - } - - last_worker = worker; - - Debug("SYNC: Worker %d synchronized\n", worker->get_id()); - - metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); - metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync); - worker->set_cfo(get_cfo()); - worker_com->set_sync_metrics(metrics); - - /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ - srslte_timestamp_t rx_time, tx_time, tx_time_prach; - srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); - srslte_timestamp_copy(&tx_time, &rx_time); - srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); - worker->set_tx_time(tx_time, next_offset); - next_offset = 0; - - Debug("SYNC: Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id()); - worker->set_tti(tti, tx_mutex_cnt); - tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; - - // Reset Uplink TX buffer to avoid mixing packets in TX queue - /* - if (prach_buffer->is_pending()) { - Info("SYNC: PRACH pending: Reset UL\n"); - radio_h->tx_end(); - }*/ - - // Check if we need to TX a PRACH - if (prach_buffer->is_ready_to_send(tti)) { - srslte_timestamp_copy(&tx_time_prach, &rx_time); - srslte_timestamp_add(&tx_time_prach, 0, prach::tx_advance_sf * 1e-3); - prach_buffer->send(radio_h, get_cfo(), worker_com->pathloss, tx_time_prach); - radio_h->tx_end(); - worker_com->p0_preamble = prach_buffer->get_p0_preamble(); - worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble); - } - - workers_pool->start_worker(worker); - - if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) { - srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]); - } - if (srslte_cell_isvalid(&cell)) { - intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); - } - break; - case 0: - Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); - out_of_sync(); - worker->release(); - worker_com->reset_ul(); - break; - default: - radio_error(); - break; - } - } else { - // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here - running = false; - } - break; - case IDLE: - if (radio_h->is_init()) { - uint32_t nsamples = 1920; - if (current_srate > 0) { - nsamples = current_srate/1000; - } - if (!radio_h->rx_now(dummy_buffer, nsamples, NULL)) { - printf("SYNC: Receiving from radio while in IDLE_RX\n"); - } - } else { - usleep(1000); - } - is_in_idle = true; - break; - } - - // Increase TTI counter and trigger MAC clock (lower priority) - mac->tti_clock(tti); - tti = (tti+1) % 10240; - } - - for (int i=0;iin_sync(); - in_sync_cnt = 0; - out_of_sync_cnt = 0; - } -} - -// Out of sync called by worker or phch_recv every 1 or 5 ms -void phch_recv::out_of_sync() { - // Send RRC out-of-sync signal after 200 ms consecutive subframes - Info("Out-of-sync %d/%d\n", out_of_sync_cnt, NOF_OUT_OF_SYNC_SF); - out_of_sync_cnt++; - if (out_of_sync_cnt >= NOF_OUT_OF_SYNC_SF) { - Info("Sending to RRC\n"); - rrc->out_of_sync(); - out_of_sync_cnt = 0; - in_sync_cnt = 0; - } -} - - - - - - - - - @@ -800,20 +869,11 @@ void phch_recv::search::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, force_N_id_2 = -1; } -void phch_recv::search::set_N_id_2(int N_id_2) { - force_N_id_2 = N_id_2; -} - void phch_recv::search::reset() { srslte_ue_sync_reset(&ue_mib_sync.ue_sync); } -float phch_recv::search::get_last_gain() -{ - return srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc); -} - float phch_recv::search::get_last_cfo() { return srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync); @@ -844,6 +904,7 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) if (p->srate_mode != SRATE_FIND) { p->srate_mode = SRATE_FIND; p->radio_h->set_rx_srate(1.92e6); + p->radio_h->set_tx_srate(1.92e6); Info("SYNC: Setting Cell Search sampling rate\n"); } @@ -901,6 +962,10 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) Info("SYNC: MIB Decoded: PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", cell->id, cell->nof_prb, cell->nof_ports, cfo/1000); + if (!srslte_cell_isvalid(cell)) { + Error("SYNC: Detected invalid cell.\n"); + return CELL_NOT_FOUND; + } return CELL_FOUND; } else if (ret == 0) { Warning("SYNC: Found PSS but could not decode PBCH\n"); @@ -927,11 +992,11 @@ phch_recv::sfn_sync::~sfn_sync() srslte_ue_mib_free(&ue_mib); } -void phch_recv::sfn_sync::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout) +void phch_recv::sfn_sync::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_subframes) { this->log_h = log_h; this->ue_sync = ue_sync; - this->timeout = timeout; + this->timeout = nof_subframes; for (int i=0;ibuffer[i] = buffer[i]; @@ -954,8 +1019,8 @@ bool phch_recv::sfn_sync::set_cell(srslte_cell_t cell) void phch_recv::sfn_sync::reset() { - srslte_ue_mib_reset(&ue_mib); cnt = 0; + srslte_ue_mib_reset(&ue_mib); } phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt, bool sfidx_only) @@ -1004,13 +1069,13 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c } } } else { - Debug("SYNC: PSS/SSS not found...\n"); + Info("SYNC: PSS/SSS not found...\n"); } cnt++; if (cnt >= timeout) { cnt = 0; - return TIMEOUT; + return SFN_NOFOUND; } return IDLE; @@ -1101,7 +1166,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_syn } phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *input_buffer, - int offset, + uint32_t offset, uint32_t sf_idx, uint32_t max_sf) { @@ -1111,17 +1176,18 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in offset = offset-sf_len/2; while (offset < 0 && sf_idx < max_sf) { + Info("INTRA: offset=%d, sf_idx=%d\n", offset, sf_idx); offset += sf_len; sf_idx ++; } - - // Fine-tune offset using RS #ifdef FINE_TUNE_OFFSET_WITH_RS float max_rsrp = -200; int best_test_offset = 0; int test_offset = 0; bool found_best = false; + + // Fine-tune offset using RS for (uint32_t n=0;n<5;n++) { test_offset = offset-2+n; @@ -1150,9 +1216,9 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in offset = found_best?best_test_offset:offset; #endif - if (offset >= 0 && offset < (int)(sf_len*max_sf)) { - uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; + if (offset >= 0 && offset < (sf_len*max_sf)) { + uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; final_offset = offset; @@ -1167,7 +1233,8 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in return MEASURE_OK; } } else { - Info("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); + Error("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); + ret = ERROR; } return ret; } @@ -1186,15 +1253,15 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) float rssi = srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb)); if (cnt == 0) { - mean_rsrp = rsrp; - mean_rsrq = rsrq; - mean_snr = snr; - mean_rssi = rssi; + mean_rsrp = rsrp; + mean_rsrq = rsrq; + mean_snr = snr; + mean_rssi = rssi; } else { - mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); - mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); - mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); - mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); + mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); + mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); + mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); + mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); } cnt++; @@ -1227,8 +1294,11 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 uint32_t max_fft_sz = srslte_symbol_sz(100); uint32_t max_sf_size = SRSLTE_SF_LEN(max_fft_sz); - sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size); - + sf_buffer[0] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*max_sf_size); + if (!sf_buffer[0]) { + fprintf(stderr, "Error allocating %d samples for scell\n", max_sf_size); + return; + } measure_p.init(sf_buffer, log_h, 1, max_sf_window); //do this different we don't need all this search window. @@ -1255,18 +1325,17 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 reset(); } +void phch_recv::scell_recv::deinit() { + srslte_sync_free(&sync_find); + free(sf_buffer[0]); +} + void phch_recv::scell_recv::reset() { current_fft_sz = 0; measure_p.reset(); } -void phch_recv::scell_recv::deinit() -{ - srslte_sync_free(&sync_find); - free(sf_buffer[0]); -} - int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS]) { uint32_t fft_sz = srslte_symbol_sz(cell.nof_prb); @@ -1333,7 +1402,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (cell_id >= 0) { // We found the same cell as before, look another N_id_2 if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) { - Info("n_id_2=%d, PCI=%d, found_cell.id=%d, cell.id=%d\n", n_id_2, cell_id, found_cell.id, cell.id); + Debug("INTRA: n_id_2=%d, PCI=%d, found_cell.id=%d, cell.id=%d\n", n_id_2, cell_id, found_cell.id, cell.id); sync_res = SRSLTE_SYNC_NOFOUND; } else { // We found a new cell ID @@ -1341,21 +1410,28 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, found_cell.nof_ports = 1; // Use port 0 only for measurement measure_p.set_cell(found_cell); + // Correct CFO + /* + srslte_cfo_correct(&sync_find.cfo_corr_frame, + input_buffer, + input_cfo_corrected, + -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); + */ + switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { - case measure::MEASURE_OK: + default: // Consider a cell to be detectable 8.1.2.2.1.1 from 36.133. Currently only using first condition if (measure_p.rsrp() > ABSOLUTE_RSRP_THRESHOLD_DBM) { - cells[nof_cells].pci = found_cell.id; cells[nof_cells].rsrp = measure_p.rsrp(); cells[nof_cells].rsrq = measure_p.rsrq(); cells[nof_cells].offset = measure_p.frame_st_idx(); Info( - "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, nof_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", + "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", nof_cells, cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, - sf_idx, nof_sf, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); + sf_idx, max_sf5, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); nof_cells++; @@ -1363,13 +1439,13 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (sic_pss_enabled) { srslte_pss_sic(&sync_find.pss, &input_buffer[sf5_cnt * 5 * sf_len + sf_len / 2 - fft_sz]); }*/ + } else { + Info("INTRA: Found neighbour cell but RSRP=%.1f dBm is below threshold (%.1f dBm)\n", + measure_p.rsrp(), ABSOLUTE_RSRP_THRESHOLD_DBM); } break; - default: - Info("INTRA: Not enough samples to measure PCI=%d\n", cell_id); - break; case measure::ERROR: - Error("Measuring neighbour cell\n"); + Error("INTRA: Measuring neighbour cell\n"); return SRSLTE_ERROR; } } @@ -1399,14 +1475,10 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, void phch_recv::meas_reset() { // Stop all measurements intra_freq_meas.clear_cells(); - if (worker_com) { - worker_com->pcell_meas_enabled = false; - } } int phch_recv::meas_start(uint32_t earfcn, int pci) { - if (earfcn == current_earfcn) { - worker_com->pcell_meas_enabled = true; + if ((int) earfcn == current_earfcn) { if (pci != (int) cell.id) { intra_freq_meas.add_cell(pci); } @@ -1419,7 +1491,7 @@ int phch_recv::meas_start(uint32_t earfcn, int pci) { } int phch_recv::meas_stop(uint32_t earfcn, int pci) { - if (earfcn == current_earfcn) { + if ((int) earfcn == current_earfcn) { intra_freq_meas.rem_cell(pci); return 0; } else { @@ -1429,6 +1501,12 @@ int phch_recv::meas_stop(uint32_t earfcn, int pci) { return -1; } +phch_recv::intra_measure::~intra_measure() { + srslte_ringbuffer_free(&ring_buffer); + scell.deinit(); + free(search_buffer); +} + void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc, srslte::log *log_h) { this->rrc = rrc; this->log_h = log_h; @@ -1455,12 +1533,6 @@ void phch_recv::intra_measure::stop() { wait_thread_finish(); } -phch_recv::intra_measure::~intra_measure() { - srslte_ringbuffer_free(&ring_buffer); - scell.deinit(); - free(search_buffer); -} - void phch_recv::intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t cell) { this->current_earfcn = earfcn; current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 7ac2ed040..d34aa90e8 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -133,6 +133,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph return false; } + srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true); srslte_chest_dl_average_subframe(&ue_dl.chest, phy->args->average_subframe_enabled); srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask); srslte_ue_ul_set_normalization(&ue_ul, true); @@ -185,6 +186,11 @@ void phch_worker::set_tti(uint32_t tti_, uint32_t tx_tti_) log_phy_lib_h->step(tti); } +void phch_worker::set_prach(cf_t *prach_ptr, float prach_power) { + this->prach_ptr = prach_ptr; + this->prach_power = prach_power; +} + void phch_worker::set_cfo(float cfo_) { cfo = cfo_; @@ -318,60 +324,70 @@ void phch_worker::work_imp() /***** Uplink Processing + Transmission *******/ - - /* Generate SR if required*/ - set_uci_sr(); - /* Check if we have UL grant. ul_phy_grant will be overwritten by new grant */ - ul_grant_available = decode_pdcch_ul(&ul_mac_grant); + bool signal_ready = false; + cf_t *signal_ptr = NULL; - /* Generate CQI reports if required, note that in case both aperiodic - and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ - if (ul_grant_available && ul_mac_grant.has_cqi_request) { - set_uci_aperiodic_cqi(); + /* Transmit PRACH if pending, or PUSCH/PUCCH otherwise */ + if (prach_ptr) { + signal_ready = true; + signal_ptr = prach_ptr; } else { - set_uci_periodic_cqi(); - } + /* Generate SR if required*/ + set_uci_sr(); - /* TTI offset for UL */ - ul_action.tti_offset = HARQ_DELAY_MS; + /* Check if we have UL grant. ul_phy_grant will be overwritten by new grant */ + ul_grant_available = decode_pdcch_ul(&ul_mac_grant); - /* Send UL grant or HARQ information (from PHICH) to MAC */ - if (ul_grant_available && ul_ack_available) { - phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); - } else if (ul_grant_available && !ul_ack_available) { - phy->mac->new_grant_ul(ul_mac_grant, &ul_action); - } else if (!ul_grant_available && ul_ack_available) { - phy->mac->harq_recv(tti, ul_ack, &ul_action); - } - - /* Set UL CFO before transmission */ - srslte_ue_ul_set_cfo(&ue_ul, cfo); - - /* Transmit PUSCH, PUCCH or SRS */ - bool signal_ready = false; - if (ul_action.tx_enabled) { - encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, - &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); - signal_ready = true; - if (ul_action.expect_ack) { - phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + /* Generate CQI reports if required, note that in case both aperiodic + and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ + if (ul_grant_available && ul_mac_grant.has_cqi_request) { + set_uci_aperiodic_cqi(); + } else { + set_uci_periodic_cqi(); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { - encode_pucch(); - signal_ready = true; - } else if (srs_is_ready_to_send()) { - encode_srs(); - signal_ready = true; - } + /* TTI offset for UL */ + ul_action.tti_offset = HARQ_DELAY_MS; + + /* Send UL grant or HARQ information (from PHICH) to MAC */ + if (ul_grant_available && ul_ack_available) { + phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); + } else if (ul_grant_available && !ul_ack_available) { + phy->mac->new_grant_ul(ul_mac_grant, &ul_action); + } else if (!ul_grant_available && ul_ack_available) { + phy->mac->harq_recv(tti, ul_ack, &ul_action); + } + + /* Set UL CFO before transmission */ + srslte_ue_ul_set_cfo(&ue_ul, cfo); + + /* Transmit PUSCH, PUCCH or SRS */ + if (ul_action.tx_enabled) { + encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, + &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); + signal_ready = true; + if (ul_action.expect_ack) { + phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + } + + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { + encode_pucch(); + signal_ready = true; + } else if (srs_is_ready_to_send()) { + encode_srs(); + signal_ready = true; + } + signal_ptr = signal_buffer[0]; + } + tr_log_end(); if (next_offset > 0) { - phy->worker_end(tx_tti, signal_ready, signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + phy->worker_end(tx_tti, signal_ready, signal_ptr, SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); } else { - phy->worker_end(tx_tti, signal_ready, &signal_buffer[0][-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + phy->worker_end(tx_tti, signal_ready, &signal_ptr[-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); } if (!dl_action.generate_ack_callback) { @@ -391,13 +407,13 @@ void phch_worker::work_imp() update_measurements(); if (chest_ok) { - if (phy->avg_rsrp_dbm > -130.0 && phy->avg_snr_db > -10.0) { + if (phy->avg_rsrp_sync_dbm > -130.0 && phy->avg_snr_db_sync > -10.0) { log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", - phy->avg_snr_db, phy->avg_rsrp_dbm); + phy->avg_snr_db_sync, phy->avg_rsrp_sync_dbm); chest_loop->in_sync(); } else { log_h->warning("SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n", - phy->avg_snr_db, phy->avg_rsrp_dbm); + phy->avg_snr_db_sync, phy->avg_rsrp_sync_dbm); chest_loop->out_of_sync(); } } @@ -429,41 +445,45 @@ void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) { } uci_data.uci_ri_len = 1; } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr); - Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); + if (sinr) { + srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr); + Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); + } } } bool phch_worker::extract_fft_and_pdcch_llr() { bool decode_pdcch = true; - /* Without a grant, we might need to do fft processing if need to decode PHICH */ - if (phy->get_pending_ack(tti) || decode_pdcch) { - - // Setup estimator filter - float w_coeff = phy->args->estimator_fil_w; - if (w_coeff > 0.0) { - srslte_chest_dl_set_smooth_filter3_coeff(&ue_dl.chest, w_coeff); - } else if (w_coeff == 0.0) { - srslte_chest_dl_set_smooth_filter(&ue_dl.chest, NULL, 0); - } - - if (!phy->args->snr_estim_alg.compare("refs")) { - srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); - } else if (!phy->args->snr_estim_alg.compare("empty")) { - srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_EMPTY); - } else { - srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS); - } - - if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { - Error("Getting PDCCH FFT estimate\n"); - return false; - } - chest_done = true; + // Do always channel estimation to keep track of out-of-sync and send measurements to RRC + + // Setup estimator filter + srslte_chest_dl_set_smooth_filter_gauss(&ue_dl.chest, + phy->args->estimator_fil_order, + phy->args->estimator_fil_stddev); + srslte_chest_dl_set_smooth_filter_auto(&ue_dl.chest, phy->args->estimator_fil_auto); + + if (!phy->args->snr_estim_alg.compare("refs")) { + srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); + } else if (!phy->args->snr_estim_alg.compare("empty")) { + srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_EMPTY); } else { - chest_done = false; + srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS); } + + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { + Error("Getting PDCCH FFT estimate\n"); + return false; + } + chest_done = true; + + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { + Error("Getting PDCCH FFT estimate\n"); + return false; + } + + chest_done = true; + if (chest_done && decode_pdcch) { /* and not in DRX mode */ float noise_estimate = phy->avg_noise; @@ -504,13 +524,13 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) srslte_ra_dl_dci_t dci_unpacked; if (type == SRSLTE_RNTI_RAR) { - Info("Looking for RNTI=0x%x\n", dl_rnti); + Debug("Looking for RNTI=0x%x\n", dl_rnti); } if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10, dl_rnti, type, &dci_msg) != 1) { if (type == SRSLTE_RNTI_RAR) { - Info("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n", + Debug("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n", 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), tti, cfi, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cell.id); } @@ -908,16 +928,16 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.format_is_subband) { // TODO: Implement subband periodic reports cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND; - cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db_cqi); cqi_report.subband.subband_label = 0; log_h->console("Warning: Subband CQI periodic reports not implemented\n"); - Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db); + Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db_cqi); } else { cqi_report.type = SRSLTE_CQI_TYPE_WIDEBAND; if (cqi_fixed >= 0) { cqi_report.wideband.wideband_cqi = cqi_fixed; } else { - cqi_report.wideband.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.wideband.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db_cqi); } if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) { cqi_report.wideband.wideband_cqi = cqi_max; @@ -927,7 +947,7 @@ void phch_worker::set_uci_periodic_cqi() cqi_report.wideband.pmi = phy->last_pmi; cqi_report.wideband.rank_is_not_one = (phy->last_ri != 0); } - Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); + Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db_cqi); } uci_data.uci_cqi_len = (uint32_t) srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; @@ -957,7 +977,7 @@ void phch_worker::set_uci_aperiodic_cqi() if (rnti_is_set) { srslte_cqi_value_t cqi_report = {0}; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; - cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db_cqi); // TODO: implement subband CQI properly cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands @@ -983,7 +1003,7 @@ void phch_worker::set_uci_aperiodic_cqi() } Info("PUSCH: Aperiodic RM30 CQI=%s, %sSNR=%.1f dB, for %d subbands\n", - cqi_str, (uci_data.uci_ri_len)?((uci_data.uci_ri == 0)?"ri=0, ":"ri=1, "):"", phy->avg_snr_db, cqi_report.subband_hl.N); + cqi_str, (uci_data.uci_ri_len)?((uci_data.uci_ri == 0)?"ri=0, ":"ri=1, "):"", phy->avg_snr_db_cqi, cqi_report.subband_hl.N); } break; case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31: @@ -1396,18 +1416,18 @@ void phch_worker::update_measurements() } } - // Average RSRQ + // Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); if (isnormal(rsrq_db)) { - if (!phy->avg_rsrq_db) { - phy->avg_rsrq_db = SRSLTE_VEC_EMA(rsrq_db, phy->avg_rsrq_db, snr_ema_coeff); - } else { + if (!(tti%phy->pcell_report_period) || !phy->avg_rsrq_db) { phy->avg_rsrq_db = rsrq_db; + } else { + phy->avg_rsrq_db = SRSLTE_VEC_CMA(rsrq_db, phy->avg_rsrq_db, tti%phy->pcell_report_period); } } - // Average RSRP - float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest); + // Average RSRP taken from CRS + float rsrp_lin = srslte_chest_dl_get_rsrp_neighbour(&ue_dl.chest); if (isnormal(rsrp_lin)) { if (!phy->avg_rsrp) { phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff); @@ -1419,18 +1439,20 @@ void phch_worker::update_measurements() /* Correct absolute power measurements by RX gain offset */ float rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset; - // Serving cell measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC + // Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC if (isnormal(rsrp_dbm)) { - if (!phy->avg_rsrp_dbm) { + if (!(tti%phy->pcell_report_period) || !phy->avg_rsrp_dbm) { phy->avg_rsrp_dbm = rsrp_dbm; } else { - phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff); - } - if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) { - phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); + phy->avg_rsrp_dbm = SRSLTE_VEC_CMA(rsrp_dbm, phy->avg_rsrp_dbm, tti%phy->pcell_report_period); } } + // Send PCell measurement + if ((tti%phy->pcell_report_period) == phy->pcell_report_period-1) { + phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); + } + // Compute PL float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power; phy->pathloss = tx_crs_power - phy->avg_rsrp_dbm; @@ -1444,20 +1466,40 @@ void phch_worker::update_measurements() phy->avg_noise = SRSLTE_VEC_EMA(cur_noise, phy->avg_noise, snr_ema_coeff); } } - - // Compute SNR - phy->avg_snr_db = 10*log10(phy->avg_rsrp/phy->avg_noise); - + + // To compute CQI use RSRP measurements from resource elements in RS since is more robust to time offset + float rsrp_lin_cqi = srslte_chest_dl_get_rsrp(&ue_dl.chest); + if (isnormal(rsrp_lin_cqi)) { + if (!phy->avg_rsrp_cqi) { + phy->avg_rsrp_cqi = SRSLTE_VEC_EMA(rsrp_lin_cqi, phy->avg_rsrp_cqi, snr_ema_coeff); + } else { + phy->avg_rsrp_cqi = rsrp_lin_cqi; + } + } + float rsrp_sync_dbm = 10*log10(rsrp_lin_cqi) + 30 - phy->rx_gain_offset; + if (isnormal(rsrp_sync_dbm)) { + if (!phy->avg_rsrp_sync_dbm) { + phy->avg_rsrp_sync_dbm = rsrp_sync_dbm; + } else { + phy->avg_rsrp_sync_dbm = SRSLTE_VEC_EMA(rsrp_sync_dbm, phy->avg_rsrp_sync_dbm, snr_ema_coeff); + } + } + + // We compute 2 SNR metrics, 1 for deciding in-sync/out-of-sync and another for CQI measurements + phy->avg_snr_db_cqi = 10*log10(phy->avg_rsrp_cqi/phy->avg_noise); // this for CQI + phy->avg_snr_db_sync = 10*log10(phy->avg_rsrp/phy->avg_noise); // this for sync + + // Store metrics dl_metrics.n = phy->avg_noise; dl_metrics.rsrp = phy->avg_rsrp_dbm; dl_metrics.rsrq = phy->avg_rsrq_db; dl_metrics.rssi = phy->avg_rssi_dbm; dl_metrics.pathloss = phy->pathloss; - dl_metrics.sinr = phy->avg_snr_db; + dl_metrics.sinr = phy->avg_snr_db_cqi; dl_metrics.turbo_iters = srslte_pdsch_last_noi(&ue_dl.pdsch); phy->set_dl_metrics(dl_metrics); - + } } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 90dbc2833..eb1b87aa7 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -96,9 +96,10 @@ void phy::set_default_args(phy_args_t *args) args->equalizer_mode = "mmse"; args->cfo_integer_enabled = false; args->cfo_correct_tol_hz = 50; - args->time_correct_period = 5; args->sss_algorithm = "full"; - args->estimator_fil_w = 0.1; + args->estimator_fil_auto = false; + args->estimator_fil_stddev = 1.0f; + args->estimator_fil_order = 4; } bool phy::check_args(phy_args_t *args) @@ -107,10 +108,6 @@ bool phy::check_args(phy_args_t *args) log_h->console("Error in PHY args: nof_phy_threads must be 1, 2 or 3\n"); return false; } - if (args->estimator_fil_w > 1.0) { - log_h->console("Error in PHY args: estimator_fil_w must be 0<=w<=1\n"); - return false; - } if (args->snr_ema_coeff > 1.0) { log_h->console("Error in PHY args: snr_ema_coeff must be 0<=w<=1\n"); return false; @@ -250,20 +247,6 @@ void phy::configure_ul_params(bool pregen_disabled) } } -void phy::cell_search_start() -{ - sf_recv.cell_search_start(); -} - -void phy::cell_search_next() -{ - sf_recv.cell_search_next(); -} - -void phy::sync_reset() { - sf_recv.reset_sync(); -} - void phy::meas_reset() { sf_recv.meas_reset(); } @@ -276,13 +259,16 @@ int phy::meas_stop(uint32_t earfcn, int pci) { return sf_recv.meas_stop(earfcn, pci); } -void phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell) -{ - sf_recv.cell_select(earfcn, phy_cell); +bool phy::cell_select(phy_cell_t *cell) { + return sf_recv.cell_select(cell); } -bool phy::cell_handover(srslte_cell_t cell) { - return sf_recv.cell_handover(cell); +phy_interface_rrc::cell_search_ret_t phy::cell_search(phy_cell_t *cell) { + return sf_recv.cell_search(cell); +} + +bool phy::cell_is_camping() { + return sf_recv.cell_is_camping(); } float phy::get_phr() @@ -348,13 +334,14 @@ int phy::prach_tx_tti() // Handle the case of a radio overflow. Resynchronise inmediatly void phy::radio_overflow() { - sf_recv.reset_sync(); + sf_recv.radio_overflow(); } void phy::reset() { Info("Resetting PHY\n"); n_ta = 0; + sf_recv.set_time_adv_sec(0); pdcch_dl_search_reset(); for(uint32_t i=0;i= 0 && nof_sf) { -void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte_timestamp_t tx_time) -{ - - // Get current TX gain - float old_gain = radio_handler->get_tx_gain(); - - // Correct CFO before transmission FIXME: UL SISO Only - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); + // Correct CFO before transmission FIXME: UL SISO Only + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); - // If power control is enabled, choose amplitude and power - if (args->ul_pwr_ctrl_en) { - // Get PRACH transmission power - float tx_power = SRSLTE_MIN(SRSLTE_PC_MAX, pathloss + target_power_dbm); - - // Get output power for amplitude 1 - radio_handler->set_tx_power(tx_power); - - // Scale signal - float digital_power = srslte_vec_avg_power_cf(signal_buffer, len); - float scale = sqrtf(pow(10,tx_power/10)/digital_power); - - srslte_vec_sc_prod_cfc(signal_buffer, scale, signal_buffer, len); - log_h->console("PRACH: Pathloss=%.2f dB, Target power %.2f dBm, TX_power %.2f dBm, TX_gain %.1f dB, scale %.2f\n", - pathloss, target_power_dbm, tx_power, radio_handler->get_tx_gain(), scale); - - } else { - float prach_gain = args->prach_gain; - if (prach_gain > 0) { - radio_handler->set_tx_gain(prach_gain); + // pad guard symbols with zeros + uint32_t nsf = (len-1)/SRSLTE_SF_LEN_PRB(cell.nof_prb)+1; + bzero(&signal_buffer[len], (nsf*SRSLTE_SF_LEN_PRB(cell.nof_prb)-len)*sizeof(cf_t)); + + *nof_sf = nsf; + + if (target_power) { + *target_power = target_power_dbm; } - Debug("TX PRACH: Power control for PRACH is disabled, setting gain to %.0f dB\n", prach_gain); + + Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, nof_sf=%d, target_power=%.1f dBm\n", + preamble_idx, cfo*15, nsf, target_power_dbm); + preamble_idx = -1; + + return signal_buffer; + } else { + return NULL; } - - void *tmp_buffer[SRSLTE_MAX_PORTS] = {signal_buffer, NULL, NULL, NULL}; - radio_handler->tx(tmp_buffer, len, tx_time); - radio_handler->tx_end(); - - Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n", - preamble_idx, cfo*15, tx_time.frac_secs); - preamble_idx = -1; - - radio_handler->set_tx_gain(old_gain); - Debug("Restoring TX gain to %.0f dB\n", old_gain); } } // namespace srsue diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index fe59bee91..b8db55e5e 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -160,7 +160,10 @@ bool ue::init(all_args_t *args_) if (args->rf.burst_preamble.compare("auto")) { radio.set_burst_preamble(atof(args->rf.burst_preamble.c_str())); } - + if (args->rf.continuous_tx.compare("auto")) { + radio.set_continuous_tx(args->rf.continuous_tx.compare("yes")?false:true); + } + radio.set_manual_calibration(&args->rf_cal); // Set PHY options @@ -226,7 +229,6 @@ bool ue::init(all_args_t *args_) } printf("...\n"); - nas.attach_request(); started = true; return true; @@ -273,6 +275,14 @@ void ue::stop() } } +bool ue::attach() { + return nas.attach_request(); +} + +bool ue::deattach() { + return nas.deattach_request(); +} + bool ue::is_attached() { return rrc.is_connected(); diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index 34db4a226..4c3cf6301 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -248,10 +248,8 @@ void gw::run_thread() return; } - const static uint32_t ATTACH_TIMEOUT_MS = 10000; - const static uint32_t ATTACH_MAX_ATTEMPTS = 3; - uint32_t attach_cnt = 0; - uint32_t attach_attempts = 0; + const static uint32_t ATTACH_WAIT_TOUT = 40; // 4 sec + uint32_t attach_wait = 0; gw_log->info("GW IP packet receiver thread run_enable\n"); @@ -278,25 +276,18 @@ void gw::run_thread() { gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU"); - while(run_enable && !pdcp->is_drb_enabled(cfg.lcid) && attach_attempts < ATTACH_MAX_ATTEMPTS) { - if (attach_cnt == 0) { - gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_attempts, ATTACH_MAX_ATTEMPTS); - nas->attach_request(); - attach_attempts++; + while(run_enable && !pdcp->is_drb_enabled(cfg.lcid) && attach_wait < ATTACH_WAIT_TOUT) { + if (!attach_wait) { + gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_wait, ATTACH_WAIT_TOUT); + if (!nas->attach_request()) { + gw_log->warning("Could not re-establish the connection\n"); + } } - attach_cnt++; - if (attach_cnt == ATTACH_TIMEOUT_MS) { - attach_cnt = 0; - } - usleep(1000); + usleep(100000); + attach_wait++; } - if (attach_attempts == ATTACH_MAX_ATTEMPTS) { - gw_log->warning("LCID=%d was not active after %d attempts\n", cfg.lcid, ATTACH_MAX_ATTEMPTS); - } - - attach_attempts = 0; - attach_cnt = 0; + attach_wait = 0; if (!run_enable) { break; diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 882f1d977..0488f4b45 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -45,10 +45,13 @@ namespace srsue { ********************************************************************/ nas::nas() - : state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), have_ctxt(false), ip_addr(0), eps_bearer_id(0) + : state(EMM_STATE_DEREGISTERED), have_guti(false), have_ctxt(false), ip_addr(0), eps_bearer_id(0) { ctxt.rx_count = 0; ctxt.tx_count = 0; + ctxt.cipher_algo = CIPHERING_ALGORITHM_ID_EEA0; + ctxt.integ_algo = INTEGRITY_ALGORITHM_ID_EIA0; + plmn_is_selected = false; } void nas::init(usim_interface_nas *usim_, @@ -63,7 +66,6 @@ void nas::init(usim_interface_nas *usim_, gw = gw_; nas_log = nas_log_; state = EMM_STATE_DEREGISTERED; - plmn_selection = PLMN_NOT_SELECTED; if (!usim->get_home_plmn_id(&home_plmn)) { nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n"); @@ -80,9 +82,11 @@ void nas::init(usim_interface_nas *usim_, have_guti = true; have_ctxt = true; } + running = true; } void nas::stop() { + running = false; write_ctxt_file(ctxt); } @@ -94,105 +98,186 @@ emm_state_t nas::get_state() { * UE interface ******************************************************************************/ -void nas::attach_request() { +/** Blocking function to Attach to the network and establish RRC connection if not established. + * The function returns true if the UE could attach correctly or false in case of error or timeout during attachment. + * + */ +bool nas::attach_request() { + rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS]; + int nof_plmns = 0; + nas_log->info("Attach Request\n"); - if (state == EMM_STATE_DEREGISTERED) { - state = EMM_STATE_REGISTERED_INITIATED; - if (plmn_selection == PLMN_NOT_SELECTED) { - nas_log->info("Starting PLMN Search...\n"); - rrc->plmn_search(); - } else if (plmn_selection == PLMN_SELECTED) { - nas_log->info("Selecting PLMN %s\n", plmn_id_to_string(current_plmn).c_str()); - rrc->plmn_select(current_plmn); - selecting_plmn = current_plmn; - } - } else if (state == EMM_STATE_REGISTERED) { - nas_log->info("NAS state is registered, selecting current PLMN\n"); - rrc->plmn_select(current_plmn, true); - } else { - nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]); - } -} + switch (state) { + case EMM_STATE_DEREGISTERED: -void nas::deattach_request() { - state = EMM_STATE_DEREGISTERED_INITIATED; - nas_log->info("Dettach request not supported\n"); -} - -/******************************************************************************* - * RRC interface - ******************************************************************************/ - -bool nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) { - - // Check if already registered - for (uint32_t i=0;iinfo("Found known PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str()); - if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) { - nas_log->info("Connecting Home PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str()); - rrc->plmn_select(plmn_id, state == EMM_STATE_REGISTERED_INITIATED); - selecting_plmn = plmn_id; - return true; + // Search PLMN is not selected + if (!plmn_is_selected) { + nas_log->info("No PLMN selected. Starting PLMN Search...\n"); + nof_plmns = rrc->plmn_search(found_plmns); + if (nof_plmns > 0) { + // Save PLMNs + known_plmns.clear(); + for (int i=0;iinfo("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(found_plmns[i].plmn_id).c_str(), + found_plmns[i].tac); + nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(found_plmns[i].plmn_id).c_str(), + found_plmns[i].tac); + } + select_plmn(); + } else if (nof_plmns == 0) { + nas_log->warning("Did not find any PLMN in the set of frequencies\n"); + return false; + } else if (nof_plmns < 0) { + nas_log->error("Error while searching for PLMNs\n"); + return false; + } } - return false; - } - } - - // Save if new PLMN - known_plmns.push_back(plmn_id); - - nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(), - tracking_area_code); - nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(), - tracking_area_code); - - if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) { - rrc->plmn_select(plmn_id, state == EMM_STATE_REGISTERED_INITIATED); - selecting_plmn = plmn_id; - return true; + // Select PLMN in request establishment of RRC connection + if (plmn_is_selected) { + rrc->plmn_select(current_plmn); + if (rrc_connect()) { + nas_log->info("NAS attached successfully.\n"); + return true; + } else { + nas_log->error("Could not attach in attach request\n"); + } + } else { + nas_log->error("PLMN is not selected because no suitable PLMN was found\n"); + } + break; + case EMM_STATE_REGISTERED: + if (rrc->is_connected()) { + nas_log->info("NAS is already registered and RRC connected\n"); + return true; + } else { + nas_log->info("NAS is already registered but RRC disconnected. Connecting now...\n"); + if (rrc_connect()) { + nas_log->info("NAS attached successfully.\n"); + return true; + } else { + nas_log->error("Could not attach from attach_request\n"); + } + } + break; + default: + nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]); } return false; } -// RRC indicates that the UE has gone through all EARFCN and finished PLMN selection -void nas::plmn_search_end() { - if (known_plmns.size() > 0) { - if (home_plmn.mcc != known_plmns[0].mcc && home_plmn.mnc != known_plmns[0].mnc) { - nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", - plmn_id_to_string(home_plmn).c_str(), - plmn_id_to_string(known_plmns[0]).c_str()); - - nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", - plmn_id_to_string(home_plmn).c_str(), - plmn_id_to_string(known_plmns[0]).c_str()); - } - rrc->plmn_select(known_plmns[0], state == EMM_STATE_REGISTERED_INITIATED); - } else { - nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n"); - if (state == EMM_STATE_REGISTERED_INITIATED && plmn_selection == PLMN_NOT_SELECTED) { - rrc->plmn_search(); - } - } +bool nas::deattach_request() { + state = EMM_STATE_DEREGISTERED_INITIATED; + nas_log->info("Dettach request not supported\n"); + return false; } + bool nas::is_attached() { return state == EMM_STATE_REGISTERED; } -bool nas::is_attaching() { - return state == EMM_STATE_REGISTERED_INITIATED; -} - -void nas::notify_connection_setup() { - nas_log->debug("State = %s\n", emm_state_text[state]); - if (EMM_STATE_REGISTERED_INITIATED == state) { - send_attach_request(); +void nas::paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) { + if (state == EMM_STATE_REGISTERED) { + nas_log->info("Received paging: requesting RRC connection establishment\n"); + if (rrc_connect()) { + nas_log->info("Attached successfully\n"); + } else { + nas_log->error("Could not attach from paging\n"); + } } else { - send_service_request(); + nas_log->warning("Received paging while in state %s\n", emm_state_text[state]); } } +void nas::set_barring(barring_t barring) { + current_barring = barring; +} + +/* Internal function that requests RRC connection, waits for positive or negative response and returns true/false + */ +bool nas::rrc_connect() { + if (rrc->is_connected()) { + nas_log->info("Already connected\n"); + return true; + } + + // Generate service request or attach request message + byte_buffer_t *dedicatedInfoNAS = pool_allocate; + if (state == EMM_STATE_REGISTERED) { + gen_service_request(dedicatedInfoNAS); + } else { + gen_attach_request(dedicatedInfoNAS); + } + + // Provide UE-Identity to RRC if have one + if (have_guti) { + LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; + s_tmsi.mmec = ctxt.guti.mme_code; + s_tmsi.m_tmsi = ctxt.guti.m_tmsi; + rrc->set_ue_idenity(s_tmsi); + } + + // Set establishment cause + LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM establish_cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; + + if (rrc->connection_request(establish_cause, dedicatedInfoNAS)) + { + nas_log->info("Connection established correctly. Waiting for Attach\n"); + + // Wait until attachment. If doing a service request is already attached + uint32_t tout = 0; + while (tout < 5000 && state != EMM_STATE_REGISTERED && running && rrc->is_connected()) { + usleep(1000); + tout++; + } + if (state == EMM_STATE_REGISTERED) { + nas_log->info("EMM Registered correctly\n"); + return true; + } else if (state == EMM_STATE_DEREGISTERED) { + nas_log->error("Timeout or received attach reject while trying to attach\n"); + nas_log->console("Failed to Attach\n"); + } else if (!rrc->is_connected()) { + nas_log->error("Was disconnected while attaching\n"); + } else { + nas_log->error("Timed out while trying to attach\n"); + } + } else { + nas_log->error("Could not establish RRC connection\n"); + pool->deallocate(dedicatedInfoNAS); + } + return false; +} + +void nas::select_plmn() { + + plmn_is_selected = false; + + // First find if Home PLMN is available + for (uint32_t i=0;iinfo("Selecting Home PLMN Id=%s\n", plmn_id_to_string(known_plmns[i]).c_str()); + plmn_is_selected = true; + current_plmn = known_plmns[i]; + return; + } + } + + // If not, select the first available PLMN + if (known_plmns.size() > 0) { + nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", + plmn_id_to_string(home_plmn).c_str(), + plmn_id_to_string(known_plmns[0]).c_str()); + + nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", + plmn_id_to_string(home_plmn).c_str(), + plmn_id_to_string(known_plmns[0]).c_str()); + plmn_is_selected = true; + current_plmn = known_plmns[0]; + } +} + + void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { uint8 pd = 0; uint8 msg_type = 0; @@ -271,16 +356,6 @@ uint32_t nas::get_ul_count() { return ctxt.tx_count; } -bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) { - if (have_guti) { - s_tmsi->mmec = ctxt.guti.mme_code; - s_tmsi->m_tmsi = ctxt.guti.m_tmsi; - return true; - } else { - return false; - } -} - bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) { if(!have_ctxt) { nas_log->error("K_asme requested before security context established\n"); @@ -350,7 +425,7 @@ bool nas::integrity_check(byte_buffer_t *pdu) return NULL; } if (pdu->N_bytes > 5) { - uint8_t exp_mac[4]; + uint8_t exp_mac[4] = {0}; uint8_t *mac = &pdu->msg[1]; int i; @@ -408,7 +483,7 @@ void nas::cipher_encrypt(byte_buffer_t *pdu) memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); break; default: - nas_log->error("Ciphering algorithmus not known"); + nas_log->error("Ciphering algorithm not known\n"); break; } } @@ -474,10 +549,10 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { return; } - LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; - LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_complete; - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept; + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept = {0}; + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_complete = {0}; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req = {0}; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept = {0}; nas_log->info("Received Attach Accept\n"); @@ -489,6 +564,11 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { if (attach_accept.guti_present) { memcpy(&ctxt.guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); have_guti = true; + // Update RRC UE-Idenity + LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; + s_tmsi.mmec = ctxt.guti.mme_code; + s_tmsi.m_tmsi = ctxt.guti.m_tmsi; + rrc->set_ue_idenity(s_tmsi); } if (attach_accept.lai_present) {} if (attach_accept.ms_id_present) {} @@ -511,7 +591,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[3]; nas_log->info("Network attach successful. APN: %s, IP: %u.%u.%u.%u\n", - act_def_eps_bearer_context_req.apn.apn.c_str(), + act_def_eps_bearer_context_req.apn.apn, act_def_eps_bearer_context_req.pdn_addr.addr[0], act_def_eps_bearer_context_req.pdn_addr.addr[1], act_def_eps_bearer_context_req.pdn_addr.addr[2], @@ -554,8 +634,6 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { // FIXME: Setup the default EPS bearer context state = EMM_STATE_REGISTERED; - current_plmn = selecting_plmn; - plmn_selection = PLMN_SELECTED; ctxt.rx_count++; @@ -599,7 +677,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { } void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) { - LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej; + LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej = {0}; liblte_mme_unpack_attach_reject_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_rej); nas_log->warning("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause); @@ -611,7 +689,9 @@ void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) { void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; + bzero(&auth_req, sizeof(LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT)); LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_res; + bzero(&auth_res, sizeof(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT)); nas_log->info("Received Authentication Request\n"); liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &auth_req); @@ -666,8 +746,8 @@ void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) { } void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu) { - LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; - LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; + LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req = {0}; + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp = {0}; liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &id_req); nas_log->info("Received Identity Request. ID type: %d\n", id_req.id_type); @@ -711,7 +791,9 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) } LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd; + bzero(&sec_mode_cmd, sizeof(LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT)); LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp; + bzero(&sec_mode_comp, sizeof(LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT)); liblte_mme_unpack_security_mode_command_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &sec_mode_cmd); nas_log->info("Received Security Mode Command ksi: %d, eea: %s, eia: %s\n", @@ -838,21 +920,19 @@ void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) { * Senders ******************************************************************************/ -void nas::send_attach_request() { - - - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; - byte_buffer_t *msg = pool_allocate; +void nas::gen_attach_request(byte_buffer_t *msg) { if (!msg) { - nas_log->error("Fatal Error: Couldn't allocate PDU in send_attach_request().\n"); + nas_log->error("Fatal Error: Couldn't allocate PDU in gen_attach_request().\n"); return; } + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + bzero(&attach_req, sizeof(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT)); - u_int32_t i; + nas_log->info("Generating attach request\n"); attach_req.eps_attach_type = LIBLTE_MME_EPS_ATTACH_TYPE_EPS_ATTACH; - for (i = 0; i < 8; i++) { + for (u_int32_t i = 0; i < 8; i++) { attach_req.ue_network_cap.eea[i] = eea_caps[i]; attach_req.ue_network_cap.eia[i] = eia_caps[i]; } @@ -915,67 +995,19 @@ void nas::send_attach_request() { pcap->write_nas(msg->msg, msg->N_bytes); } - nas_log->info("Sending attach request\n"); - rrc->write_sdu(cfg.lcid, msg); - if (have_ctxt) { ctxt.tx_count++; } } -void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) { - LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - nas_log->info("Generating PDN Connectivity Request\n"); - - // Set the PDN con req parameters - pdn_con_req.eps_bearer_id = 0x00; // Unassigned bearer ID - pdn_con_req.proc_transaction_id = 0x01; // First transaction ID - pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; - pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST; - - // Set the optional flags - pdn_con_req.esm_info_transfer_flag_present = false; //FIXME: Check if this is needed - if (cfg.apn == "") { - pdn_con_req.apn_present = false; - } else { - pdn_con_req.apn_present = true; - LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; - apn.apn = cfg.apn; - pdn_con_req.apn = apn; - } - pdn_con_req.protocol_cnfg_opts_present = false; - pdn_con_req.device_properties_present = false; - - // Pack the message - liblte_mme_pack_pdn_connectivity_request_msg(&pdn_con_req, msg); -} - -void nas::send_security_mode_reject(uint8_t cause) { - byte_buffer_t *msg = pool_allocate; +void nas::gen_service_request(byte_buffer_t *msg) { if (!msg) { - nas_log->error("Fatal Error: Couldn't allocate PDU in send_security_mode_reject().\n"); + nas_log->error("Fatal Error: Couldn't allocate PDU in gen_service_request().\n"); return; } - LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej; - sec_mode_rej.emm_cause = cause; - liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) msg); - if(pcap != NULL) { - pcap->write_nas(msg->msg, msg->N_bytes); - } - nas_log->info("Sending security mode reject\n"); - rrc->write_sdu(cfg.lcid, msg); -} - -void nas::send_identity_response() {} - -void nas::send_service_request() { - byte_buffer_t *msg = pool_allocate; - if (!msg) { - nas_log->error("Fatal Error: Couldn't allocate PDU in send_service_request().\n"); - return; - } + nas_log->info("Generating service request\n"); // Pack the service request message directly msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); @@ -1001,11 +1033,56 @@ void nas::send_service_request() { pcap->write_nas(msg->msg, msg->N_bytes); } - nas_log->info("Sending service request\n"); - rrc->write_sdu(cfg.lcid, msg); ctxt.tx_count++; } +void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) { + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req = {0}; + + nas_log->info("Generating PDN Connectivity Request\n"); + + // Set the PDN con req parameters + pdn_con_req.eps_bearer_id = 0x00; // Unassigned bearer ID + pdn_con_req.proc_transaction_id = 0x01; // First transaction ID + pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; + pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST; + + // Set the optional flags + pdn_con_req.esm_info_transfer_flag_present = false; //FIXME: Check if this is needed + if (cfg.apn == "") { + pdn_con_req.apn_present = false; + } else { + pdn_con_req.apn_present = true; + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn = {0}; + strncpy(apn.apn, cfg.apn.c_str(), LIBLTE_STRING_LEN); + pdn_con_req.apn = apn; + } + pdn_con_req.protocol_cnfg_opts_present = false; + pdn_con_req.device_properties_present = false; + + // Pack the message + liblte_mme_pack_pdn_connectivity_request_msg(&pdn_con_req, msg); +} + +void nas::send_security_mode_reject(uint8_t cause) { + byte_buffer_t *msg = pool_allocate; + if (!msg) { + nas_log->error("Fatal Error: Couldn't allocate PDU in send_security_mode_reject().\n"); + return; + } + + LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej = {0}; + sec_mode_rej.emm_cause = cause; + liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) msg); + if(pcap != NULL) { + pcap->write_nas(msg->msg, msg->N_bytes); + } + nas_log->info("Sending security mode reject\n"); + rrc->write_sdu(cfg.lcid, msg); +} + +void nas::send_identity_response() {} + void nas::send_esm_information_response() {} diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 05286e05c..0f5975705 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -49,13 +49,14 @@ namespace srsue { rrc::rrc() :state(RRC_STATE_IDLE) ,drb_up(false) - ,sysinfo_index(0) ,serving_cell(NULL) { n310_cnt = 0; n311_cnt = 0; serving_cell = new cell_t(); neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS); + initiated = false; + running = false; } rrc::~rrc() @@ -98,18 +99,12 @@ void rrc::init(phy_interface_rrc *phy_, // Use MAC timers mac_timers = mac_timers_; state = RRC_STATE_IDLE; - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; + plmn_is_selected = false; - ho_syncing = false; - - thread_running = true; - start(); + security_is_activated = false; pthread_mutex_init(&mutex, NULL); - first_stimsi_attempt = false; - args.ue_category = SRSLTE_UE_CATEGORY; args.supported_bands[0] = 7; args.nof_supported_bands = 1; @@ -117,22 +112,25 @@ void rrc::init(phy_interface_rrc *phy_, t300 = mac_timers->timer_get_unique_id(); t301 = mac_timers->timer_get_unique_id(); + t302 = mac_timers->timer_get_unique_id(); t310 = mac_timers->timer_get_unique_id(); t311 = mac_timers->timer_get_unique_id(); t304 = mac_timers->timer_get_unique_id(); + dedicatedInfoNAS = NULL; + ueIdentity_configured = false; + transaction_id = 0; // Register logging handler with liblte_rrc liblte_rrc_log_register_handler(this, liblte_rrc_handler); - nof_sib1_trials = 0; - last_win_start = 0; + cell_clean_cnt = 0; + + ho_start = false; pending_mob_reconf = false; - connection_requested = false; - // Set default values for all layers set_rrc_default(); set_phy_default(); @@ -141,23 +139,26 @@ void rrc::init(phy_interface_rrc *phy_, measurements.init(this); // set seed for rand (used in attach) srand(time(NULL)); + + running = true; + start(); + initiated = true; } void rrc::stop() { - thread_running = false; + running = false; + cmd_msg_t msg; + msg.command = cmd_msg_t::STOP; + cmd_q.push(msg); wait_thread_finish(); } -void rrc::run_tti(uint32_t tti) { - measurements.run_tti(tti); -} - rrc_state_t rrc::get_state() { return state; } bool rrc::is_connected() { - return (state >= RRC_STATE_CONNECTED && state < RRC_STATE_LEAVE_CONNECTED); + return (RRC_STATE_CONNECTED == state); } bool rrc::have_drb() { @@ -168,151 +169,447 @@ void rrc::set_args(rrc_args_t *args) { memcpy(&this->args, args, sizeof(rrc_args_t)); } +/* + * Low priority thread to run functions that can not be executed from main thread + */ +void rrc::run_thread() { + while(running) { + cmd_msg_t msg = cmd_q.wait_pop(); + switch(msg.command) { + case cmd_msg_t::STOP: + return; + case cmd_msg_t::PCCH: + process_pcch(msg.pdu); + break; + } + } +} + + /* * * RRC State Machine * */ -void rrc::run_thread() { +void rrc::run_tti(uint32_t tti) { - uint32_t failure_test = 0; - uint32_t cell_clean_cnt = 0; + if (!initiated) { + return; + } - while (thread_running) { + /* We can not block in this thread because it is called from + * the MAC TTI timer and needs to return immediatly to perform other + * tasks. Therefore in this function we use trylock() instead of lock() and + * skip function if currently locked, since none of the functions here is urgent + */ + if (!pthread_mutex_trylock(&mutex)) { - switch(state) { - /* Procedures in IDLE state 36.304 Sec 4 */ + // Process pending PHY measurements in IDLE/CONNECTED + process_phy_meas(); + + // Run state machine + rrc_log->debug("State %s\n", rrc_state_text[state]); + switch (state) { case RRC_STATE_IDLE: - // If camping on the cell, it will receive SI and paging from PLMN - if (phy->sync_status()) { - // If attempting to attach, reselect cell - if (nas->is_attaching()) { - rrc_log->info("RRC IDLE: NAS has pending data and camping on cell, connecting...\n"); - plmn_select_rrc(selected_plmn_id); - } - // If not camping on a cell - } else { - // If NAS is attached, perform cell reselection on current PLMN - if (nas->is_attached()) { - rrc_log->info("RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell...\n"); - plmn_select_rrc(selected_plmn_id); - } else if (nas->is_attaching()) { - rrc_log->info("RRC IDLE: NAS is attaching, searching again PLMN\n"); - plmn_search(); - } - // If not attached, PLMN selection will be triggered from higher layers - } - break; - case RRC_STATE_PLMN_START: - rrc_log->info("RRC PLMN Search: Starting cell search\n"); - plmn_select_timeout = 0; - phy->cell_search_start(); - state = RRC_STATE_PLMN_SELECTION; - break; - case RRC_STATE_PLMN_SELECTION: - plmn_select_timeout++; - if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) { - rrc_log->info("RRC PLMN Search: timeout expired\n"); - rrc_log->console("\nRRC PLMN Search: timeout expired.\n"); - state = RRC_STATE_IDLE; - } - break; - case RRC_STATE_CELL_SELECTING: - /* During cell selection, apply SIB configurations if available or receive them if not. - * Cell is selected when all SIBs downloaded or applied. + /* CAUTION: The execution of cell_search() and cell_selection() take more than 1 ms + * and will slow down MAC TTI ticks. This has no major effect at the moment because + * the UE is in IDLE but we could consider splitting MAC and RRC threads to avoid this */ - if (phy->sync_status()) { - if (!serving_cell->has_sib1()) { - si_acquire_state = SI_ACQUIRE_SIB1; - sysinfo_index = 0; - } else if (!serving_cell->has_sib2()) { - si_acquire_state = SI_ACQUIRE_SIB2; - } else { - apply_sib2_configs(serving_cell->sib2ptr()); - state = RRC_STATE_CELL_SELECTED; + + // If attached but not camping on the cell, perform cell reselection + if (nas->is_attached()) { + rrc_log->debug("Running cell selection and reselection in IDLE\n"); + switch(cell_selection()) { + case rrc::CHANGED_CELL: + // New cell has been selected, start receiving PCCH + mac->pcch_start_rx(); + break; + case rrc::NO_CELL: + rrc_log->warning("Could not find any cell to camp on\n"); + break; + case rrc::SAME_CELL: + if (!phy->cell_is_camping()) { + rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); + serving_cell->in_sync = false; + } + break; } - run_si_acquisition_procedure(); - } - break; - case RRC_STATE_CELL_SELECTED: - - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - - /* The cell is selected when the SIBs are received and applied. - * If we were in RRC_CONNECTED and arrive here it means a RLF occurred and we are in Reestablishment procedure. - * If T311 is running means there is a reestablishment in progress, send ConnectionReestablishmentRequest. - * If not, do a ConnectionRequest if NAS is established or go to IDLE an camp on cell otherwise. - */ - if (mac_timers->timer_get(t311)->is_running()) { - // - rrc_log->info("RRC Cell Selected: Sending connection reestablishment...\n"); - con_restablish_cell_reselected(); - state = RRC_STATE_CONNECTING; - connecting_timeout = 0; - } else if (nas->is_attaching() || connection_requested) { - rrc_log->info("RRC Cell Selected: Sending connection request...\n"); - connection_requested = false; - send_con_request(); - state = RRC_STATE_CONNECTING; - connecting_timeout = 0; - } else { - rrc_log->info("RRC Cell Selected: Starting paging and going to IDLE...\n"); - mac->pcch_start_rx(); - state = RRC_STATE_LEAVE_CONNECTED; - } - break; - case RRC_STATE_CONNECTING: - connecting_timeout++; - if (connecting_timeout >= RRC_CONNECTING_TIMEOUT) { - // Select another cell - rrc_log->info("RRC Connecting: timeout expired. Selecting next cell\n"); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; } break; case RRC_STATE_CONNECTED: - /* - failure_test++; - if (failure_test >= 100) { - mac_interface_rrc::ue_rnti_t ue_rnti; - mac->get_rntis(&ue_rnti); - send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, ue_rnti.crnti); - }*/ - // Take measurements, cell reselection, etc - break; - case RRC_STATE_HO_PREPARE: - if (ho_prepare()) { - state = RRC_STATE_HO_PROCESS; - } else { - state = RRC_STATE_CONNECTED; + if (ho_start) { + ho_start = false; + if (!ho_prepare()) { + con_reconfig_failed(); + } + } + measurements.run_tti(tti); + if (go_idle) { + go_idle = false; + leave_connected(); } break; - case RRC_STATE_HO_PROCESS: - // wait for HO to finish - break; - case RRC_STATE_LEAVE_CONNECTED: - usleep(60000); - leave_connected(); - // Move to RRC_IDLE - state = RRC_STATE_IDLE; - break; - default: - break; + default:break; } - if (state == RRC_STATE_CONNECTED || RRC_STATE_IDLE) { - cell_clean_cnt++; - if (cell_clean_cnt==1000) { - clean_neighbours(); - cell_clean_cnt = 0; + + // Clean old neighbours + cell_clean_cnt++; + if (cell_clean_cnt == 1000) { + clean_neighbours(); + cell_clean_cnt = 0; + } + pthread_mutex_unlock(&mutex); + } // Skip TTI if mutex is locked +} + + + + + + + + + +/******************************************************************************* +* +* +* +* NAS interface: PLMN search and RRC connection establishment +* +* +* +*******************************************************************************/ + +uint16_t rrc::get_mcc() { + return serving_cell->get_mcc(); +} + +uint16_t rrc::get_mnc() { + return serving_cell->get_mnc(); +} + +/* NAS interface to search for available PLMNs. + * It goes through all known frequencies, synchronizes and receives SIB1 for each to extract PLMN. + * The function is blocking and waits until all frequencies have been + * searched and PLMNs are obtained. + * + * This function is thread-safe with connection_request() + */ +int rrc::plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) +{ + // Mutex with connect + pthread_mutex_lock(&mutex); + + rrc_log->info("Starting PLMN search\n"); + uint32_t nof_plmns = 0; + phy_interface_rrc::cell_search_ret_t ret; + do { + ret = cell_search(); + if (ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND) { + if (serving_cell->has_sib1()) { + // Save PLMN and TAC to NAS + for (uint32_t i = 0; i < serving_cell->nof_plmns(); i++) { + if (nof_plmns < MAX_FOUND_PLMNS) { + found_plmns[nof_plmns].plmn_id = serving_cell->get_plmn(i); + found_plmns[nof_plmns].tac = serving_cell->get_tac(); + nof_plmns++; + } else { + rrc_log->error("No more space for plmns (%d)\n", nof_plmns); + } + } + } else { + rrc_log->error("SIB1 not acquired\n"); } } - usleep(1000); + } while (ret.last_freq == phy_interface_rrc::cell_search_ret_t::MORE_FREQS && + ret.found != phy_interface_rrc::cell_search_ret_t::ERROR); + + // Process all pending measurements before returning + process_phy_meas(); + + pthread_mutex_unlock(&mutex); + + if (ret.found == phy_interface_rrc::cell_search_ret_t::ERROR) { + return -1; + } else { + return nof_plmns; } } +/* This is the NAS interface. When NAS requests to select a PLMN we have to + * connect to either register or because there is pending higher layer traffic. + */ +void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { + plmn_is_selected = true; + selected_plmn_id = plmn_id; + + rrc_log->info("PLMN Selected %s\n", plmn_id_to_string(plmn_id).c_str()); +} + +/* 5.3.3.2 Initiation of RRC Connection Establishment procedure + * + * Higher layers request establishment of RRC connection while UE is in RRC_IDLE + * + * This procedure selects a suitable cell for transmission of RRCConnectionRequest and configures + * it. Sends connectionRequest message and returns if message transmitted successfully. + * It does not wait until completition of Connection Establishment procedure + */ +bool rrc::connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, + srslte::byte_buffer_t *dedicatedInfoNAS) +{ + + if (!plmn_is_selected) { + rrc_log->error("Trying to connect but PLMN not selected.\n"); + return false; + } + + if (state != RRC_STATE_IDLE) { + rrc_log->warning("Requested RRC connection establishment while not in IDLE\n"); + return false; + } + + if (mac_timers->timer_get(t302)->is_running()) { + rrc_log->info("Requested RRC connection establishment while T302 is running\n"); + nas->set_barring(nas_interface_rrc::BARRING_MO_DATA); + return false; + } + + bool ret = false; + + pthread_mutex_lock(&mutex); + + rrc_log->info("Initiation of Connection establishment procedure\n"); + + // Perform cell selection & reselection for the selected PLMN + cs_ret_t cs_ret = cell_selection(); + + // .. and SI acquisition + if (phy->cell_is_camping()) { + + // Set default configurations + set_phy_default(); + set_mac_default(); + + // CCCH configuration applied already at start + // timeAlignmentCommon applied in configure_serving_cell + + rrc_log->info("Configuring serving cell...\n"); + if (configure_serving_cell()) { + + mac_timers->timer_get(t300)->reset(); + mac_timers->timer_get(t300)->run(); + + // Send connectionRequest message to lower layers + send_con_request(cause); + + // Save dedicatedInfoNAS SDU + if (this->dedicatedInfoNAS) { + rrc_log->warning("Received a new dedicatedInfoNAS SDU but there was one still in queue. Removing it\n"); + pool->deallocate(this->dedicatedInfoNAS); + } + this->dedicatedInfoNAS = dedicatedInfoNAS; + + // Wait until t300 stops due to RRCConnectionSetup/Reject or expiry + while (mac_timers->timer_get(t300)->is_running()) { + usleep(1000); + } + + if (state == RRC_STATE_CONNECTED) { + // Received ConnectionSetup + ret = true; + } else if (mac_timers->timer_get(t300)->is_expired()) { + // T300 is expired: 5.3.3.6 + rrc_log->info("Timer T300 expired: ConnectionRequest timed out\n"); + mac->reset(); + set_mac_default(); + rlc->reestablish(); + } else { + // T300 is stopped but RRC not Connected is because received Reject: Section 5.3.3.8 + rrc_log->info("Timer T300 stopped: Received ConnectionReject\n"); + mac->reset(); + set_mac_default(); + } + + } else { + rrc_log->error("Configuring serving cell\n"); + } + } else { + switch(cs_ret) { + case SAME_CELL: + rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); + serving_cell->in_sync = false; + break; + case CHANGED_CELL: + rrc_log->warning("Selected a new cell but could not camp on. Setting out-of-sync.\n"); + serving_cell->in_sync = false; + break; + default: + rrc_log->warning("Could not find any suitable cell to connect\n"); + } + } + + pthread_mutex_unlock(&mutex); + return ret; +} + +void rrc::set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) { + ueIdentity_configured = true; + ueIdentity = s_tmsi; + rrc_log->info("Set ue-Identity to 0x%x:0x%x\n", ueIdentity.mmec, ueIdentity.m_tmsi); +} + +/* Retrieves all required SIB or configures them if already retrieved before + */ +bool rrc::configure_serving_cell() { + + if (!phy->cell_is_camping()) { + rrc_log->error("Trying to configure Cell while not camping on it\n"); + return false; + } + // Apply configurations if already retrieved SIB2 + if (serving_cell->has_sib2()) { + apply_sib2_configs(serving_cell->sib2ptr()); + } + // Obtain the rest of required SIBs (configuration is applied when received) + for (uint32_t i = 0; i < NOF_REQUIRED_SIBS; i++) { + if (!serving_cell->has_sib(i)) { + rrc_log->info("Cell has no SIB%d. Obtaining SIB%d\n", i+1, i+1); + if (!si_acquire(i)) { + rrc_log->info("Timeout while acquiring SIB%d\n", i+1); + if (i < 2) { + return false; + } + } + } else { + rrc_log->info("Cell has SIB%d\n", i+1); + } + } + return true; +} + + + + + + +/******************************************************************************* +* +* +* +* PHY interface: neighbour and serving cell measurements and out-of-sync/in-sync +* +* +* +*******************************************************************************/ + +/* This function is called from a PHY worker thus must return very quickly. + * Queue the values of the measurements and process them from the RRC thread + */ +void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { + uint32_t pci = 0; + uint32_t earfcn = 0; + if (earfcn_i < 0) { + earfcn = (uint32_t) serving_cell->get_earfcn(); + } else { + earfcn = (uint32_t) earfcn_i; + } + if (pci_i < 0) { + pci = (uint32_t) serving_cell->get_pci(); + } else { + pci = (uint32_t) pci_i; + } + phy_meas_t new_meas = {rsrp, rsrq, tti, earfcn, pci}; + phy_meas_q.push(new_meas); + rrc_log->info("MEAS: New measurement pci=%d, rsrp=%.1f dBm.\n", pci, rsrp); +} + +/* Processes all pending PHY measurements in queue. Must be called from a mutexed function + */ +void rrc::process_phy_meas() { + while(!phy_meas_q.empty()) { + rrc_log->debug("MEAS: Processing measurement. %lu measurements in queue\n", phy_meas_q.size()); + process_new_phy_meas(phy_meas_q.front()); + phy_meas_q.pop(); + } +} + +void rrc::process_new_phy_meas(phy_meas_t meas) +{ + float rsrp = meas.rsrp; + float rsrq = meas.rsrq; + uint32_t tti = meas.tti; + uint32_t earfcn = meas.earfcn; + uint32_t pci = meas.pci; + + // Measurements in RRC_CONNECTED go through measurement class to log reports etc. + if (state != RRC_STATE_IDLE) { + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); + + // Measurements in RRC_IDLE update serving cell + } else { + + // Update serving cell + if (serving_cell->equals(earfcn, pci)) { + serving_cell->set_rsrp(rsrp); + // Or update/add neighbour cell + } else { + add_neighbour_cell(earfcn, pci, rsrp); + } + } +} + +// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1) +void rrc::out_of_sync() +{ + + // CAUTION: We do not lock in this function since they are called from real-time threads + + serving_cell->in_sync = false; + rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n", + rrc_state_text[state], n310_cnt, + mac_timers->timer_get(t311)->is_running()?"running":"stop", + mac_timers->timer_get(t310)->is_running()?"running":"stop"); + if (state == RRC_STATE_CONNECTED) { + if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { + n310_cnt++; + if (n310_cnt == N310) { + rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", + N310, mac_timers->timer_get(t310)->get_timeout()); + mac_timers->timer_get(t310)->reset(); + mac_timers->timer_get(t310)->run(); + n310_cnt = 0; + } + } + } +} + +// Recovery of physical layer problems (5.3.11.2) +void rrc::in_sync() +{ + + // CAUTION: We do not lock in this function since they are called from real-time threads + + serving_cell->in_sync = true; + if (mac_timers->timer_get(t310)->is_running()) { + n311_cnt++; + if (n311_cnt == N311) { + mac_timers->timer_get(t310)->stop(); + n311_cnt = 0; + rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311); + } + } +} + + + + + + + + + + @@ -335,73 +632,97 @@ uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint return (period*10*(1+tti/(period*10))+(offset*10)+sf)%10240; // the 1 means next opportunity } -void rrc::run_si_acquisition_procedure() +/* Implemnets the SI acquisition procedure + * Configures the MAC/PHY scheduling to retrieve SI messages. The function is blocking and will not + * return until SIB is correctly received or timeout + */ +bool rrc::si_acquire(uint32_t sib_index) { uint32_t tti; uint32_t si_win_start=0, si_win_len=0; uint16_t period; + uint32_t sched_index; uint32_t x, sf, offset; - const int SIB1_SEARCH_TIMEOUT = 30; - switch (si_acquire_state) { - case SI_ACQUIRE_SIB1: + uint32_t last_win_start = 0; + uint32_t timeout = 0; + + while(timeout < SIB_SEARCH_TIMEOUT_MS && !serving_cell->has_sib(sib_index)) { + + bool instruct_phy = false; + + if (sib_index == 0) { + // Instruct MAC to look for SIB1 tti = mac->get_current_tti(); si_win_start = sib_start_tti(tti, 2, 0, 5); if (last_win_start == 0 || - (srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000)) - { + (srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000)) { last_win_start = si_win_start; - mac->bcch_start_rx(si_win_start, 1); - rrc_log->info("Instructed MAC to search for SIB1, win_start=%d, win_len=%d, interval=%d\n", - si_win_start, 1, srslte_tti_interval(last_win_start, tti)); - nof_sib1_trials++; - if (nof_sib1_trials >= SIB1_SEARCH_TIMEOUT) { - if (state == RRC_STATE_CELL_SELECTING) { - select_next_cell_in_plmn(); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - } else if (state == RRC_STATE_PLMN_SELECTION) { - phy->cell_search_next(); - } - nof_sib1_trials = 0; - } + si_win_len = 1; + instruct_phy = true; } - break; - case SI_ACQUIRE_SIB2: - // Instruct MAC to look for next SIB - if(sysinfo_index < serving_cell->sib1ptr()->N_sched_info) { - si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length]; - x = sysinfo_index*si_win_len; + period = 20; + sched_index = 0; + } else { + // Instruct MAC to look for SIB2..13 + if (serving_cell->has_sib1()) { + + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1 = serving_cell->sib1ptr(); + + // SIB2 scheduling + if (sib_index == 1) { + period = liblte_rrc_si_periodicity_num[sib1->sched_info[0].si_periodicity]; + sched_index = 0; + } else { + // SIB3+ scheduling Section 5.2.3 + if (sib_index >= 2) { + bool found = false; + for (uint32_t i=0;iN_sched_info && !found;i++) { + for (uint32_t j=0;jsched_info[i].N_sib_mapping_info && !found;j++) { + if ((uint32_t) sib1->sched_info[i].sib_mapping_info[j].sib_type == sib_index - 2) { + period = liblte_rrc_si_periodicity_num[sib1->sched_info[i].si_periodicity]; + sched_index = i; + } + } + } + if (!found) { + rrc_log->error("Could not find SIB%d scheduling in SIB1\n", sib_index+1); + return false; + } + } + } + si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; + x = sched_index*si_win_len; sf = x%10; offset = x/10; tti = mac->get_current_tti(); - period = liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[sysinfo_index].si_periodicity]; si_win_start = sib_start_tti(tti, period, offset, sf); - si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length]; + si_win_len = liblte_rrc_si_window_length_num[sib1->si_window_length]; if (last_win_start == 0 || (srslte_tti_interval(tti, last_win_start) > period*10 && srslte_tti_interval(tti, last_win_start) < 1000)) { last_win_start = si_win_start; - - mac->bcch_start_rx(si_win_start, si_win_len); - rrc_log->info("Instructed MAC to search for system info=%d, win_start=%d, win_len=%d\n", - sysinfo_index, si_win_start, si_win_len); + instruct_phy = true; } - } else { - // We've received all SIBs, move on to connection request - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTED; + rrc_log->error("Trying to receive SIB%d but SIB1 not received\n", sib_index+1); } - break; - default: - break; + } + + // Instruct MAC to decode SIB + if (instruct_phy && !serving_cell->has_sib(sib_index)) { + mac->bcch_start_rx(si_win_start, si_win_len); + rrc_log->info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d, period=%d, sched_index=%d\n", + sib_index+1, si_win_start, si_win_len, period, sched_index); + } + usleep(1000); + timeout++; } + return serving_cell->has_sib(sib_index); } @@ -412,94 +733,155 @@ void rrc::run_si_acquisition_procedure() - - /******************************************************************************* * * * -* PLMN selection, cell selection/reselection and acquisition of SI procedures +* Cell selection, reselection and neighbour cell database management * * * *******************************************************************************/ -uint16_t rrc::get_mcc() { - return serving_cell->get_mcc(); -} - -uint16_t rrc::get_mnc() { - return serving_cell->get_mnc(); -} - -void rrc::plmn_search() { - state = RRC_STATE_PLMN_START; -} - -/* This is the NAS interface. When NAS requests to select a PLMN we have to - * connect to either register or because there is pending higher layer traffic. +/* Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet */ -void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool connect_request) { - connection_requested = connect_request; - plmn_select_rrc(plmn_id); -} +phy_interface_rrc::cell_search_ret_t rrc::cell_search() +{ + phy_interface_rrc::phy_cell_t new_cell; -/* This is called by RRC only. In this case, we do not want to connect, just camp on the - * selected PLMN - */ -void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { - pthread_mutex_lock(&mutex); + phy_interface_rrc::cell_search_ret_t ret = phy->cell_search(&new_cell); - // If already camping on the selected PLMN, select this cell - if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) { - if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) { - rrc_log->info("Already camping on selected PLMN\n"); - } else { - selected_plmn_id = plmn_id; + switch(ret.found) { + case phy_interface_rrc::cell_search_ret_t::CELL_FOUND: + rrc_log->info("Cell found in this frequency. Setting new serving cell...\n"); - if (serving_cell->plmn_equals(selected_plmn_id) && serving_cell->in_sync) { - rrc_log->info("PLMN Id=%s selected, Selecting serving cell earfcn=%d, pci=%d, status=%d\n", - plmn_id_to_string(plmn_id).c_str(), serving_cell->get_earfcn(), serving_cell->phy_cell.id, - phy->sync_status()); - if (!phy->sync_status()) { - phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell); + // Create cell with NaN RSRP. Will be updated by new_phy_meas() during SIB search. + if (!add_neighbour_cell(new_cell, NAN)) { + rrc_log->info("No more space for neighbour cells\n"); + break; + } + set_serving_cell(new_cell); + + if (phy->cell_is_camping()) { + if (!serving_cell->has_sib1()) { + rrc_log->info("Cell has no SIB1. Obtaining SIB1\n"); + if (!si_acquire(0)) { + rrc_log->error("Timeout while acquiring SIB1\n"); + } + } else { + rrc_log->info("Cell has SIB1\n"); } } else { - bool found = false; - for (uint32_t i=0;iplmn_equals(selected_plmn_id)) { - rrc_log->info("PLMN Id=%s selected, Selecting neighbour cell PCI=%d\n", plmn_id_to_string(plmn_id).c_str(), neighbour_cells[i]->get_pci()); - phy->cell_select(neighbour_cells[i]->get_earfcn(), neighbour_cells[i]->phy_cell); - found = true; + rrc_log->warning("Could not camp on found cell. Trying next one...\n"); + } + break; + case phy_interface_rrc::cell_search_ret_t::CELL_NOT_FOUND: + rrc_log->info("No cells found.\n"); + break; + case phy_interface_rrc::cell_search_ret_t::ERROR: + rrc_log->error("In cell search. Finishing PLMN search\n"); + break; + } + return ret; +} + +/* Cell selection procedure 36.304 5.2.3 + * Select the best cell to camp on among the list of known cells + */ +rrc::cs_ret_t rrc::cell_selection() +{ + // Neighbour cells are sorted in descending order of RSRP + for (uint32_t i = 0; i < neighbour_cells.size(); i++) { + if (/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells + * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ + neighbour_cells[i]->in_sync) // matches S criteria + { + // If currently connected, verify cell selection criteria + if (!serving_cell->in_sync || + (cell_selection_criteria(neighbour_cells[i]->get_rsrp()) && + neighbour_cells[i]->get_rsrp() > serving_cell->get_rsrp() + 5)) + { + // Try to select Cell + set_serving_cell(i); + rrc_log->info("Selected cell idx=%d, PCI=%d, EARFCN=%d\n", + i, serving_cell->get_pci(), serving_cell->get_earfcn()); + rrc_log->console("Selected cell PCI=%d, EARFCN=%d\n", + serving_cell->get_pci(), serving_cell->get_earfcn()); + + if (phy->cell_select(&serving_cell->phy_cell)) { + if (configure_serving_cell()) { + rrc_log->info("Selected and configured cell successfully\n"); + return CHANGED_CELL; + } else { + rrc_log->error("While configuring serving cell\n"); } - } - if (!found) { - rrc_log->warning("Could not find any cell for the selected PLMN. Searching another PLMN\n"); - plmn_search(); - pthread_mutex_unlock(&mutex); - return; + } else { + serving_cell->in_sync = false; + rrc_log->warning("Could not camp on selected cell\n"); } } } - - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; - } else { - rrc_log->warning("Requested PLMN select in incorrect state %s\n", rrc_state_text[state]); } - pthread_mutex_unlock(&mutex); + if (serving_cell->in_sync) { + return SAME_CELL; + } + // If can not find any suitable cell, search again + rrc_log->info("Cell selection and reselection in IDLE did not find any suitable cell. Searching again\n"); + // If can not camp on any cell, search again for new cells + phy_interface_rrc::cell_search_ret_t ret = cell_search(); + + return (ret.found == phy_interface_rrc::cell_search_ret_t::CELL_FOUND)?CHANGED_CELL:NO_CELL; } -void rrc::set_serving_cell(uint32_t earfcn, uint32_t pci) { - int cell_idx = find_neighbour_cell(earfcn, pci); +// Cell selection criteria Section 5.2.3.2 of 36.304 +bool rrc::cell_selection_criteria(float rsrp, float rsrq) +{ + if (get_srxlev(rsrp) > 0) { + return true; + } else { + return false; + } +} + +float rrc::get_srxlev(float Qrxlevmeas) { + // TODO: Do max power limitation + float Pcompensation = 0; + return Qrxlevmeas - (cell_resel_cfg.Qrxlevmin + cell_resel_cfg.Qrxlevminoffset) - Pcompensation; +} + +float rrc::get_squal(float Qqualmeas) { + return Qqualmeas - (cell_resel_cfg.Qqualmin + cell_resel_cfg.Qqualminoffset); +} + +// Cell reselection in IDLE Section 5.2.4 of 36.304 +void rrc::cell_reselection(float rsrp, float rsrq) +{ + // Intra-frequency cell-reselection criteria + + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -95.0) { + // UE may not perform intra-frequency measurements. + phy->meas_reset(); + // keep measuring serving cell + phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); + } else { + // UE must start intra-frequency measurements + phy->meas_start(phy->get_current_earfcn(), -1); + } + + // TODO: Inter-frequency cell reselection +} + +// Set new serving cell +void rrc::set_serving_cell(phy_interface_rrc::phy_cell_t phy_cell) { + int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); if (cell_idx >= 0) { set_serving_cell(cell_idx); } else { - rrc_log->error("Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d\n", earfcn, pci); + rrc_log->error("Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d\n", phy_cell.earfcn, phy_cell.cell.id); } } +// Set new serving cell void rrc::set_serving_cell(uint32_t cell_idx) { if (cell_idx < neighbour_cells.size()) @@ -515,7 +897,7 @@ void rrc::set_serving_cell(uint32_t cell_idx) { // Move serving cell to neighbours list if (serving_cell->is_valid()) { // Make sure it does not exist already - int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->phy_cell.id); + int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->get_pci()); if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { printf("Error serving cell is already in the neighbour list. Removing it\n"); neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end()); @@ -529,153 +911,14 @@ void rrc::set_serving_cell(uint32_t cell_idx) { // Set new serving cell serving_cell = new_serving_cell; - rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%zd\n", - cell_idx, serving_cell->get_earfcn(), serving_cell->phy_cell.id, neighbour_cells.size()); + rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%lu\n", + cell_idx, serving_cell->get_earfcn(), serving_cell->get_pci(), neighbour_cells.size()); } else { rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); } } -bool rrc::select_next_cell_in_plmn() { - // Neighbour cells are sorted in descending order of RSRP - for (uint32_t i = 0; i < neighbour_cells.size(); i++) { - if (/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells - * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ - neighbour_cells[i]->in_sync) // matches S criteria - { - // If currently connected, verify cell selection criteria - if (!serving_cell->in_sync || - (cell_selection_eval(neighbour_cells[i]->get_rsrp()) && - neighbour_cells[i]->get_rsrp() > serving_cell->get_rsrp() + 5)) - { - // Try to select Cell - set_serving_cell(i); - rrc_log->info("Selected cell idx=%d, PCI=%d, EARFCN=%d\n", - i, serving_cell->phy_cell.id, serving_cell->get_earfcn()); - rrc_log->console("Selected cell PCI=%d, EARFCN=%d\n", - serving_cell->phy_cell.id, serving_cell->get_earfcn()); - phy->cell_select(serving_cell->get_earfcn(), serving_cell->phy_cell); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; - return true; - } - } - } - return false; -} - -void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn_i, int pci_i) { - - pthread_mutex_lock(&mutex); - - if (earfcn_i < 0 || pci_i < 0) { - earfcn_i = serving_cell->get_earfcn(); - pci_i = serving_cell->phy_cell.id; - } - - uint32_t earfcn = (uint32_t) earfcn_i; - uint32_t pci = (uint32_t) pci_i; - - // Measurements in RRC_CONNECTED go through measuremnt class to log reports etc. - if (state != RRC_STATE_IDLE) { - measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); - - // Measurements in RRC_IDLE update serving cell and check for reselection - } else { - - // Update serving cell - if (serving_cell->equals(earfcn, pci)) { - cell_reselection_eval(rsrp, rsrq); - serving_cell->set_rsrp(rsrp); - rrc_log->info("MEAS: New measurement serving cell in IDLE, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); - - // Or update/add neighbour cell - } else { - if (add_neighbour_cell(earfcn, pci, rsrp)) { - rrc_log->info("MEAS: New measurement neighbour in IDLE, PCI=%d, RSRP=%.1f dBm.\n", pci, rsrp); - } else { - rrc_log->info("MEAS: Neighbour Cell in IDLE PCI=%d, RSRP=%.1f dBm not added. Worse than current neighbours\n", pci, rsrp); - } - } - - // Evaluate if we need to select a new cell - select_next_cell_in_plmn(); - } - pthread_mutex_unlock(&mutex); -} - -// PHY indicates that has gone through all known EARFCN -void rrc::earfcn_end() { - rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); - - // If searching for PLMN, indicate NAS we scanned all frequencies - if (state == RRC_STATE_PLMN_SELECTION) { - nas->plmn_search_end(); - } else { - rrc_log->info("Restarting Cell search...\n"); - phy->cell_search_start(); - } -} - -/* PHY begins camping in a cell. RRC updates RSRP measurement, - * proceeds with PLMN selection/cell search if applicable and sets - * new cell as current serving cell */ -void rrc::cell_camping(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { - - int cell_idx = -1; - bool found = true; - - pthread_mutex_lock(&mutex); - - if (serving_cell->equals(earfcn, phy_cell.id)) { - serving_cell->set_rsrp(rsrp); - } else { - // Check if cell is in our list of neighbour cells - cell_idx = find_neighbour_cell(earfcn, phy_cell.id); - if (cell_idx >= 0) { - set_serving_cell(cell_idx); - serving_cell->set_rsrp(rsrp); - } else { - found = false; - if (!add_neighbour_cell(earfcn, phy_cell, rsrp)) { - rrc_log->info( - "No more space for neighbour cells (detected cell RSRP=%.1f dBm worse than current %d neighbours)\n", - rsrp, - NOF_NEIGHBOUR_CELLS); - } else { - set_serving_cell(earfcn, phy_cell.id); - serving_cell->set_rsrp(rsrp); - } - } - } - - pthread_mutex_unlock(&mutex); - - if (state == RRC_STATE_PLMN_SELECTION && serving_cell->has_sib1()) { - bool ret = false; - for (uint32_t j = 0; j < serving_cell->sib1ptr()->N_plmn_ids; j++) { - ret |= nas->plmn_found(serving_cell->sib1ptr()->plmn_id[j].id, serving_cell->sib1ptr()->tracking_area_code); - } - // If any of the PLMNs in this cell is selected, search next cell - if (!ret) { - phy->cell_search_next(); - } - } else if (state < RRC_STATE_CONNECTING) { - state = RRC_STATE_CELL_SELECTING; - } - - rrc_log->info("%s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", - found?"Updating":"Adding", - cell_idx>=0?"neighbour":"serving", earfcn, phy_cell.id, rsrp); - - if (ho_syncing && phy_cell.id == ho_target_pci) { - ho_synced(ho_target_pci); - } - -} - bool sort_rsrp(cell_t *u1, cell_t *u2) { return u1->greater(u2); } @@ -692,13 +935,13 @@ std::vector::iterator rrc::delete_neighbour(std::vector::itera return neighbour_cells.erase(it); } +/* Called by main RRC thread to remove neighbours from which measurements have not been received in a while + */ void rrc::clean_neighbours() { struct timeval now; gettimeofday(&now, NULL); - pthread_mutex_lock(&mutex); - std::vector::iterator it = neighbour_cells.begin(); while(it != neighbour_cells.end()) { if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) { @@ -708,7 +951,6 @@ void rrc::clean_neighbours() ++it; } } - pthread_mutex_unlock(&mutex); } // Sort neighbour cells by decreasing order of RSRP @@ -730,7 +972,7 @@ void rrc::sort_neighbour_cells() if (neighbour_cells.size() > 0) { char ordered[512]; int n=0; - n += snprintf(ordered, 512, "[pci=%d, rsrsp=%.2f", neighbour_cells[0]->phy_cell.id, neighbour_cells[0]->get_rsrp()); + n += snprintf(ordered, 512, "[pci=%d, rsrp=%.2f", neighbour_cells[0]->phy_cell.cell.id, neighbour_cells[0]->get_rsrp()); for (uint32_t i=1;iget_pci(), neighbour_cells[i]->get_rsrp()); } @@ -760,31 +1002,32 @@ bool rrc::add_neighbour_cell(cell_t *new_cell) { // If only neighbour PCI is provided, copy full cell from serving cell bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { - srslte_cell_t serving_phy; - serving_phy = serving_cell->phy_cell; - serving_phy.id = pci; - return add_neighbour_cell(earfcn, serving_phy, rsrp); + phy_interface_rrc::phy_cell_t phy_cell; + phy_cell = serving_cell->phy_cell; + phy_cell.earfcn = earfcn; + phy_cell.cell.id = pci; + return add_neighbour_cell(phy_cell, rsrp); } -bool rrc::add_neighbour_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { - if (earfcn == 0) { - earfcn = serving_cell->get_earfcn(); +bool rrc::add_neighbour_cell(phy_interface_rrc::phy_cell_t phy_cell, float rsrp) { + if (phy_cell.earfcn == 0) { + phy_cell.earfcn = serving_cell->get_earfcn(); } // First check if already exists - int cell_idx = find_neighbour_cell(earfcn, phy_cell.id); + int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); - rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.id, earfcn, cell_idx); + rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.cell.id, phy_cell.earfcn, cell_idx); - // If exists, update RSRP, sort again and return - if (cell_idx >= 0) { + // If exists, update RSRP if provided, sort again and return + if (cell_idx >= 0 && isnormal(rsrp)) { neighbour_cells[cell_idx]->set_rsrp(rsrp); sort_neighbour_cells(); return true; } // If not, create a new one - cell_t *new_cell = new cell_t(phy_cell, earfcn, rsrp); + cell_t *new_cell = new cell_t(phy_cell, rsrp); return add_neighbour_cell(new_cell); } @@ -798,105 +1041,17 @@ int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) { return -1; } -// Cell reselection in IDLE Section 5.2.4 of 36.304 -void rrc::cell_reselection_eval(float rsrp, float rsrq) -{ - // Intra-frequency cell-reselection criteria - - if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -95.0) { - // UE may not perform intra-frequency measurements. - phy->meas_reset(); - // keep measuring serving cell - phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); - } else { - // UE must start intra-frequency measurements - phy->meas_start(phy->get_current_earfcn(), -1); - } - - // TODO: Inter-frequency cell reselection -} - -// Cell selection in IDLE Section 5.2.3.2 of 36.304 -bool rrc::cell_selection_eval(float rsrp, float rsrq) -{ - if (get_srxlev(rsrp) > 0) { - return true; - } else { - return false; - } -} - -float rrc::get_srxlev(float Qrxlevmeas) { - // TODO: Do max power limitation - float Pcompensation = 0; - return Qrxlevmeas - (cell_resel_cfg.Qrxlevmin + cell_resel_cfg.Qrxlevminoffset) - Pcompensation; -} - -float rrc::get_squal(float Qqualmeas) { - return Qqualmeas - (cell_resel_cfg.Qqualmin + cell_resel_cfg.Qqualminoffset); -} - - /******************************************************************************* * * * -* Detection of Radio-Link Failures +* Other functions * * * *******************************************************************************/ -// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1) -void rrc::out_of_sync() { - rrc_log->info("Received out-of-sync state %s. n310=%d, t311=%s, t310=%s\n", - rrc_state_text[state], n310_cnt, - mac_timers->timer_get(t311)->is_running()?"running":"stop", - mac_timers->timer_get(t310)->is_running()?"running":"stop"); - if (state == RRC_STATE_CONNECTED) { - if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { - n310_cnt++; - if (n310_cnt == N310) { - rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", - N310, mac_timers->timer_get(t310)->get_timeout()); - mac_timers->timer_get(t310)->reset(); - mac_timers->timer_get(t310)->run(); - n310_cnt = 0; - } - } - } else if (state != RRC_STATE_LEAVE_CONNECTED) { - if (!mac_timers->timer_get(t311)->is_running()) { - if (serving_cell->in_sync) { - rrc_log->info("Detected out-of-sync while in IDLE. Resetting sync\n"); - phy->sync_reset(); - } else { - rrc_log->info("Detected out-of-sync while in IDLE. Selecting another cell in the PLMN\n"); - if (!select_next_cell_in_plmn()) { - rrc_log->info("Could not find any available cell in this PLMN. Searching PLMN again.\n"); - plmn_search(); - } - } - } else { - rrc_log->info("Detected out-of-sync while T311 is running\n"); - } - } - serving_cell->in_sync = false; -} - -// Recovery of physical layer problems (5.3.11.2) -void rrc::in_sync() { - serving_cell->in_sync = true; - if (mac_timers->timer_get(t310)->is_running()) { - n311_cnt++; - if (n311_cnt == N311) { - mac_timers->timer_get(t310)->stop(); - n311_cnt = 0; - rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311); - } - } -} - /* Detection of radio link failure (5.3.11.3) * Upon T310 expiry, RA problem or RLC max retx */ @@ -905,12 +1060,9 @@ void rrc::radio_link_failure() { rrc_log->warning("Detected Radio-Link Failure\n"); rrc_log->console("Warning: Detected Radio-Link Failure\n"); - if (state != RRC_STATE_CONNECTED) { - state = RRC_STATE_LEAVE_CONNECTED; - } else { - mac_interface_rrc::ue_rnti_t uernti; - mac->get_rntis(&uernti); - send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, uernti.crnti); + if (state == RRC_STATE_CONNECTED) { + // Initiate connection re-establishment procedure + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE); } } @@ -939,21 +1091,19 @@ void rrc::timer_expired(uint32_t timeout_id) { radio_link_failure(); } else if (timeout_id == t311) { rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); - state = RRC_STATE_LEAVE_CONNECTED; - } else if (timeout_id == t300) { - rrc_log->info("Timer T300 expired: ConnectionRequest failed. Reset MAC and restablished RLC.\n"); - rlc->reestablish(); - mac->reset(); - set_mac_default(); - state = RRC_STATE_IDLE; - nas->plmn_search_end(); + go_idle = true; } else if (timeout_id == t301) { if (state == RRC_STATE_IDLE) { rrc_log->info("Timer T301 expired: Already in IDLE.\n"); } else { rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); - state = RRC_STATE_LEAVE_CONNECTED; + go_idle = true; } + } else if (timeout_id == t302) { + rrc_log->info("Timer T302 expired. Informing NAS about barrier alleviation\n"); + nas->set_barring(nas_interface_rrc::BARRING_NONE); + } else if (timeout_id == t300) { + // Do nothing, handled in connection_request() } else if (timeout_id == t304) { rrc_log->console("Timer T304 expired: Handover failed\n"); ho_failed(); @@ -980,16 +1130,17 @@ void rrc::timer_expired(uint32_t timeout_id) { * *******************************************************************************/ -void rrc::send_con_request() { +void rrc::send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause) { rrc_log->debug("Preparing RRC Connection Request\n"); - LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; + bzero(&ul_ccch_msg, sizeof(LIBLTE_RRC_UL_CCCH_MSG_STRUCT)); // Prepare ConnectionRequest packet ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; - if (nas->get_s_tmsi(&s_tmsi)) { + if (ueIdentity_configured) { ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI; - ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = s_tmsi; + ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi.m_tmsi = ueIdentity.m_tmsi; + ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi.mmec = ueIdentity.mmec; } else { ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE; // TODO use proper RNG @@ -1000,17 +1151,25 @@ void rrc::send_con_request() { ul_ccch_msg.msg.rrc_con_req.ue_id.random = random_id; } - ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; + ul_ccch_msg.msg.rrc_con_req.cause = cause; - mac_timers->timer_get(t300)->reset(); - mac_timers->timer_get(t300)->run(); send_ul_ccch_msg(); - } /* RRC connection re-establishment procedure (5.3.7) */ -void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint16_t crnti) +void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause) { + bzero(&ul_ccch_msg, sizeof(LIBLTE_RRC_UL_CCCH_MSG_STRUCT)); + + uint16_t crnti; + if (cause == LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE) { + crnti = ho_src_rnti; + } else { + mac_interface_rrc::ue_rnti_t uernti; + mac->get_rntis(&uernti); + crnti = uernti.crnti; + } + // Compute shortMAC-I uint8_t varShortMAC[128], varShortMAC_packed[16]; bzero(varShortMAC, 128); @@ -1070,31 +1229,39 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, set_phy_default(); mac->reset(); set_mac_default(); - phy->sync_reset(); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; - state = RRC_STATE_CELL_SELECTING; -} -// Actions following cell reselection 5.3.7.3 -void rrc::con_restablish_cell_reselected() -{ - liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + // Perform cell selection in accordance to 36.304 + if (cell_selection_criteria(serving_cell->get_rsrp()) && serving_cell->in_sync) { + if (phy->cell_select(&serving_cell->phy_cell)) { - 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(); - - send_ul_ccch_msg(); + if (mac_timers->timer_get(t311)->is_running()) { + // Actions following cell reselection while T311 is running 5.3.7.3 + rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); + liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + mac_timers->timer_get(t301)->reset(); + mac_timers->timer_get(t301)->run(); + mac_timers->timer_get(t311)->stop(); + send_ul_ccch_msg(); + } else { + rrc_log->info("T311 expired while selecting cell. Going to IDLE\n"); + go_idle = true; + } + } else { + rrc_log->warning("Could not re-synchronize with cell.\n"); + } + } else { + rrc_log->info("Selected cell no longer suitable for camping. Going to IDLE\n"); + go_idle = true; + } } void rrc::send_con_restablish_complete() { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); + rrc_log->debug("Preparing RRC Connection Reestablishment Complete\n"); rrc_log->console("RRC Connected\n"); - state = RRC_STATE_CONNECTED; // Prepare ConnectionSetupComplete packet ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_REEST_COMPLETE; @@ -1104,11 +1271,9 @@ void rrc::send_con_restablish_complete() { } void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); rrc_log->debug("Preparing RRC Connection Setup Complete\n"); - state = RRC_STATE_CONNECTED; - rrc_log->console("RRC Connected\n"); - // Prepare ConnectionSetupComplete packet ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_SETUP_COMPLETE; ul_dcch_msg.msg.rrc_con_setup_complete.registered_mme_present = false; @@ -1123,6 +1288,8 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) { } void rrc::send_ul_info_transfer(byte_buffer_t *nas_msg) { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); + rrc_log->debug("Preparing RX Info Transfer\n"); // Prepare RX INFO packet @@ -1137,6 +1304,7 @@ void rrc::send_ul_info_transfer(byte_buffer_t *nas_msg) { } void rrc::send_security_mode_complete() { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); rrc_log->debug("Preparing Security Mode Complete\n"); ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE; @@ -1146,6 +1314,7 @@ void rrc::send_security_mode_complete() { } void rrc::send_rrc_con_reconfig_complete() { + bzero(&ul_dcch_msg, sizeof(LIBLTE_RRC_UL_DCCH_MSG_STRUCT)); rrc_log->debug("Preparing RRC Connection Reconfig Complete\n"); ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE; @@ -1172,46 +1341,36 @@ bool rrc::ho_prepare() { mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]); if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present && mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != serving_cell->get_earfcn()) { - rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); + rrc_log->error("Received mobilityControlInfo for inter-frequency handover\n"); + return false; } // Save serving cell and current configuration ho_src_cell = *serving_cell; - phy->get_config(&ho_src_phy_cfg); - mac->get_config(&ho_src_mac_cfg); mac_interface_rrc::ue_rnti_t uernti; mac->get_rntis(&uernti); ho_src_rnti = uernti.crnti; // Reset/Reestablish stack - mac->bcch_stop_rx(); // FIXME: change function name + mac->clear_rntis(); phy->meas_reset(); mac->wait_uplink(); pdcp->reestablish(); rlc->reestablish(); mac->reset(); - // PHY is reset inside cell_handover() function + phy->reset(); mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); - rrc_log->info("Selecting new cell pci=%d\n", neighbour_cells[target_cell_idx]->get_pci()); - if (!phy->cell_handover(neighbour_cells[target_cell_idx]->phy_cell)) { + if (!phy->cell_select(&neighbour_cells[target_cell_idx]->phy_cell)) { rrc_log->error("Could not synchronize with target cell pci=%d. Trying to return to source PCI\n", neighbour_cells[target_cell_idx]->get_pci()); - ho_failed(); return false; } - ho_target_pci = neighbour_cells[target_cell_idx]->phy_cell.id; - ho_syncing = true; - } - return true; -} -void rrc::ho_synced(uint32_t current_pci) -{ - ho_syncing = false; - if (current_pci == ho_target_pci) { + set_serving_cell(target_cell_idx); + if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) { rrc_log->info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n", mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index, @@ -1228,14 +1387,14 @@ void rrc::ho_synced(uint32_t current_pci) ncc = mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count; if (mob_reconf.sec_cnfg_ho.intra_lte.key_change_ind) { rrc_log->console("keyChangeIndicator in securityConfigHO not supported\n"); - return; + return false; } if (mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg_present) { cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.cipher_alg; integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.int_alg; rrc_log->info("Changed Ciphering to %s and Integrity to %s\n", - ciphering_algorithm_id_text[cipher_algo], - integrity_algorithm_id_text[integ_algo]); + ciphering_algorithm_id_text[cipher_algo], + integrity_algorithm_id_text[integ_algo]); } } @@ -1245,23 +1404,20 @@ void rrc::ho_synced(uint32_t current_pci) pdcp->config_security_all(k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(); - } else { - rrc_log->error("HO: Synchronized with incorrect cell. Target PCI=%d, current PCI=%d\n", ho_target_pci, current_pci); - ho_failed(); } - return; + return true; } void rrc::ho_ra_completed(bool ra_successful) { if (pending_mob_reconf) { - measurements.ho_finish(); - - if (mob_reconf.meas_cnfg_present) { - measurements.parse_meas_config(&mob_reconf.meas_cnfg); - } - if (ra_successful) { + measurements.ho_finish(); + + if (mob_reconf.meas_cnfg_present) { + measurements.parse_meas_config(&mob_reconf.meas_cnfg); + } + mac_timers->timer_get(t304)->stop(); apply_rr_config_common_ul(&mob_reconf.mob_ctrl_info.rr_cnfg_common); @@ -1269,79 +1425,99 @@ void rrc::ho_ra_completed(bool ra_successful) { apply_rr_config_dedicated(&mob_reconf.rr_cnfg_ded); } } + // T304 will expiry and send ho_failure rrc_log->info("HO %ssuccessful\n", ra_successful?"":"un"); rrc_log->console("HO %ssuccessful\n", ra_successful?"":"un"); pending_mob_reconf = false; - if (ra_successful) { - state = RRC_STATE_CONNECTED; - } } else { rrc_log->error("Received HO random access completed but no pending mobility reconfiguration info\n"); } } -// This is T304 expiry 5.3.5.6 -void rrc::ho_failed() { - - // Instruct PHY to resync with source PCI - if (!phy->cell_handover(ho_src_cell.phy_cell)) { - rrc_log->error("Could not synchronize with target cell pci=%d. Going to PLMN Search\n", ho_src_cell.get_pci()); - plmn_search(); - return; +bool rrc::con_reconfig_ho(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) +{ + if (reconfig->mob_ctrl_info.target_pci == phy->get_current_pci()) { + rrc_log->warning("Received HO command to own cell\n"); + return false; } - // Set previous PHY/MAC configuration - phy->set_config(&ho_src_phy_cfg); - mac->set_config(&ho_src_mac_cfg); + rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); + rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", + reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); - // Start the Reestablishment Procedure - send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE, ho_src_rnti); + // store mobilityControlInfo + memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); + pending_mob_reconf = true; + + ho_start = true; + + return true; } -void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) { - uint32_t i; +// Handle RRC Reconfiguration without MobilityInformation Section 5.3.5.3 +bool rrc::con_reconfig(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) { + if (reconfig->rr_cnfg_ded_present) { + if (!apply_rr_config_dedicated(&reconfig->rr_cnfg_ded)) { + return false; + } + } + if (reconfig->meas_cnfg_present) { + if (!measurements.parse_meas_config(&reconfig->meas_cnfg)) { + return false; + } + } + + send_rrc_con_reconfig_complete(); + + byte_buffer_t *nas_sdu; + for (uint32_t i = 0; i < reconfig->N_ded_info_nas; i++) { + nas_sdu = pool_allocate; + if (nas_sdu) { + memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); + nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; + nas->write_pdu(RB_ID_SRB1, nas_sdu); + } else { + rrc_log->error("Fatal Error: Couldn't allocate PDU in handle_rrc_con_reconfig().\n"); + return false; + } + } + return true; +} + +// HO failure from T304 expiry 5.3.5.6 +void rrc::ho_failed() { + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE); +} + +// Reconfiguration failure or Section 5.3.5.5 +void rrc::con_reconfig_failed() +{ + // Set previous PHY/MAC configuration + phy->set_config(&previous_phy_cfg); + mac->set_config(&previous_mac_cfg); + + if (security_is_activated) { + // Start the Reestablishment Procedure + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE); + } else { + go_idle = true; + } +} + +void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig) +{ + phy->get_config(&previous_phy_cfg); + mac->get_config(&previous_mac_cfg); if (reconfig->mob_ctrl_info_present) { - - if (reconfig->mob_ctrl_info.target_pci == phy->get_current_pci()) { - rrc_log->warning("Received HO command to own cell\n"); - send_rrc_con_reconfig_complete(); - } else { - rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); - rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", - reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); - - // store mobilityControlInfo - memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); - pending_mob_reconf = true; - - state = RRC_STATE_HO_PREPARE; + if (!con_reconfig_ho(reconfig)) { + con_reconfig_failed(); } - } else { - // Section 5.3.5.3 - if (reconfig->rr_cnfg_ded_present) { - apply_rr_config_dedicated(&reconfig->rr_cnfg_ded); - } - if (reconfig->meas_cnfg_present) { - measurements.parse_meas_config(&reconfig->meas_cnfg); - } - - send_rrc_con_reconfig_complete(); - - byte_buffer_t *nas_sdu; - for (i = 0; i < reconfig->N_ded_info_nas; i++) { - nas_sdu = pool_allocate; - if (nas_sdu) { - memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); - nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; - nas->write_pdu(lcid, nas_sdu); - } else { - rrc_log->error("Fatal Error: Couldn't allocate PDU in handle_rrc_con_reconfig().\n"); - return; - } + if (!con_reconfig(reconfig)) { + con_reconfig_failed(); } } } @@ -1349,8 +1525,8 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU /* Actions upon reception of RRCConnectionRelease 5.3.8.3 */ void rrc::rrc_connection_release() { // Save idleModeMobilityControlInfo, etc. - state = RRC_STATE_LEAVE_CONNECTED; rrc_log->console("Received RRC Connection Release\n"); + go_idle = true; } /* Actions upon leaving RRC_CONNECTED 5.3.12 */ @@ -1358,9 +1534,9 @@ void rrc::leave_connected() { rrc_log->console("RRC IDLE\n"); rrc_log->info("Leaving RRC_CONNECTED state\n"); - si_acquire_state = SI_ACQUIRE_IDLE; - last_win_start = 0; + state = RRC_STATE_IDLE; drb_up = false; + security_is_activated = false; measurements.reset(); pdcp->reset(); rlc->reset(); @@ -1372,8 +1548,9 @@ void rrc::leave_connected() mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t311)->stop(); mac_timers->timer_get(t304)->stop(); - if (phy->sync_status()) { - // Instruct MAC to look for P-RNTI + rrc_log->info("Going RRC_IDLE\n"); + if (phy->cell_is_camping()) { + // Receive paging mac->pcch_start_rx(); // Instruct PHY to measure serving cell for cell reselection phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); @@ -1395,30 +1572,26 @@ void rrc::leave_connected() * *******************************************************************************/ void rrc::write_pdu_bcch_bch(byte_buffer_t *pdu) { - if (state == RRC_STATE_PLMN_SELECTION) { - // Do we need to do something with BCH? - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH BCH message received."); - pool->deallocate(pdu); - } else { - rrc_log->warning("Received BCCH BCH in incorrect state\n"); - } + // Do we need to do something with BCH? + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH BCH message received."); + pool->deallocate(pdu); } void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { - mac->bcch_stop_rx(); + mac->clear_rntis(); rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH DLSCH message received."); rrc_log->info("BCCH DLSCH message Stack latency: %ld us\n", pdu->get_latency_us()); - LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg; + LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg = {0}; srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8); bit_buf.N_bits = pdu->N_bytes * 8; pool->deallocate(pdu); liblte_rrc_unpack_bcch_dlsch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dlsch_msg); for(uint32_t i=0; iinfo("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]); + rrc_log->info("Processing SIB%d (%d/%d)\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type], i, dlsch_msg.N_sibs); - if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) { + if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type) { serving_cell->set_sib1(&dlsch_msg.sibs[i].sib.sib1); handle_sib1(); } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !serving_cell->has_sib2()) { @@ -1432,28 +1605,22 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { handle_sib13(); } } - - last_win_start = 0; - - if(serving_cell->has_sib2()) { - sysinfo_index++; - rrc_log->info("Increasing sysinfo_index=%d\n", sysinfo_index); - } } void rrc::handle_sib1() { + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1 = serving_cell->sib1ptr(); rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", serving_cell->get_cell_id()&0xfff, - liblte_rrc_si_window_length_num[serving_cell->sib1ptr()->si_window_length], - liblte_rrc_si_periodicity_num[serving_cell->sib1ptr()->sched_info[0].si_periodicity]); + liblte_rrc_si_window_length_num[sib1->si_window_length], + liblte_rrc_si_periodicity_num[sib1->sched_info[0].si_periodicity]); // Print SIB scheduling info uint32_t i,j; - for(i=0;isib1ptr()->N_sched_info;i++){ - for(j=0;jsib1ptr()->sched_info[i].N_sib_mapping_info;j++){ - LIBLTE_RRC_SIB_TYPE_ENUM t = serving_cell->sib1ptr()->sched_info[i].sib_mapping_info[j].sib_type; - LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving_cell->sib1ptr()->sched_info[i].si_periodicity; + for(i=0;iN_sched_info;i++){ + for(j=0;jsched_info[i].N_sib_mapping_info;j++){ + LIBLTE_RRC_SIB_TYPE_ENUM t = sib1->sched_info[i].sib_mapping_info[j].sib_type; + LIBLTE_RRC_SI_PERIODICITY_ENUM p = sib1->sched_info[i].si_periodicity; rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n", liblte_rrc_sib_type_num[t], liblte_rrc_si_periodicity_num[p]); @@ -1461,29 +1628,8 @@ void rrc::handle_sib1() } // Set TDD Config - if(serving_cell->sib1ptr()->tdd) { - phy->set_config_tdd(&serving_cell->sib1ptr()->tdd_cnfg); - } - - // Send PLMN and TAC to NAS - std::stringstream ss; - for (uint32_t i = 0; i < serving_cell->sib1ptr()->N_plmn_ids; i++) { - nas->plmn_found(serving_cell->sib1ptr()->plmn_id[i].id, serving_cell->sib1ptr()->tracking_area_code); - } - - // Jump to next state - switch(state) { - case RRC_STATE_CELL_SELECTING: - si_acquire_state = SI_ACQUIRE_SIB2; - break; - case RRC_STATE_PLMN_SELECTION: - si_acquire_state = SI_ACQUIRE_IDLE; - rrc_log->info("SI Acquisition done. Searching next cell...\n"); - usleep(5000); - phy->cell_search_next(); - break; - default: - si_acquire_state = SI_ACQUIRE_IDLE; + if(sib1->tdd) { + phy->set_config_tdd(&sib1->tdd_cnfg); } } @@ -1539,12 +1685,19 @@ void rrc::handle_sib13() * *******************************************************************************/ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { + cmd_msg_t msg; + msg.pdu = pdu; + msg.command = cmd_msg_t::PCCH; + cmd_q.push(msg); +} + +void rrc::process_pcch(byte_buffer_t *pdu) { if (pdu->N_bytes > 0 && pdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BITS) { rrc_log->info_hex(pdu->msg, pdu->N_bytes, "PCCH message received %d bytes\n", pdu->N_bytes); rrc_log->info("PCCH message Stack latency: %ld us\n", pdu->get_latency_us()); rrc_log->console("PCCH message received %d bytes\n", pdu->N_bytes); - LIBLTE_RRC_PCCH_MSG_STRUCT pcch_msg; + LIBLTE_RRC_PCCH_MSG_STRUCT pcch_msg = {0}; srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8); bit_buf.N_bits = pdu->N_bytes * 8; pool->deallocate(pdu); @@ -1554,12 +1707,10 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { pcch_msg.paging_record_list_size = LIBLTE_RRC_MAX_PAGE_REC; } - LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; - if (!nas->get_s_tmsi(&s_tmsi)) { - rrc_log->info("No S-TMSI present in NAS\n"); + if (!ueIdentity_configured) { + rrc_log->warning("Received paging message but no ue-Identity is configured\n"); return; } - LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi_paged; for (uint32_t i = 0; i < pcch_msg.paging_record_list_size; i++) { s_tmsi_paged = &pcch_msg.paging_record_list[i].ue_identity.s_tmsi; @@ -1569,15 +1720,16 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { rrc_log->console("Received paging (%d/%d) for UE %x:%x\n", i + 1, pcch_msg.paging_record_list_size, pcch_msg.paging_record_list[i].ue_identity.s_tmsi.mmec, pcch_msg.paging_record_list[i].ue_identity.s_tmsi.m_tmsi); - if (s_tmsi.mmec == s_tmsi_paged->mmec && s_tmsi.m_tmsi == s_tmsi_paged->m_tmsi) { - rrc_log->info("S-TMSI match in paging message\n"); - rrc_log->console("S-TMSI match in paging message\n"); - mac->pcch_stop_rx(); + if (ueIdentity.mmec == s_tmsi_paged->mmec && ueIdentity.m_tmsi == s_tmsi_paged->m_tmsi) { if (RRC_STATE_IDLE == state) { - rrc_log->info("RRC in IDLE state - sending connection request.\n"); - connection_requested = true; - state = RRC_STATE_CELL_SELECTED; + rrc_log->info("S-TMSI match in paging message\n"); + rrc_log->console("S-TMSI match in paging message\n"); + nas->paging(s_tmsi_paged); + } else { + rrc_log->warning("Received paging while in CONNECT\n"); } + } else { + rrc_log->info("Received paging for unknown identity\n"); } } } @@ -1655,18 +1807,12 @@ void rrc::send_ul_dcch_msg() void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str()); - switch (state) { - case RRC_STATE_CONNECTING: - send_con_setup_complete(sdu); - break; - case RRC_STATE_CONNECTED: - send_ul_info_transfer(sdu); - break; - default: - rrc_log->error("SDU received from NAS while RRC state = %s\n", rrc_state_text[state]); - break; + if (state == RRC_STATE_IDLE) { + rrc_log->warning("Received ULInformationTransfer SDU when in IDLE\n"); + return; } + rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str()); + send_ul_info_transfer(sdu); } void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { @@ -1698,30 +1844,40 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) { switch (dl_ccch_msg.msg_type) { case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ: - rrc_log->info("Connection Reject received. Wait time: %d\n", + // 5.3.3.8 + rrc_log->info("Received ConnectionReject. Wait time: %d\n", dl_ccch_msg.msg.rrc_con_rej.wait_time); - // Stop T300 timer + rrc_log->console("Received ConnectionReject. Wait time: %d\n", + dl_ccch_msg.msg.rrc_con_rej.wait_time); + mac_timers->timer_get(t300)->stop(); - state = RRC_STATE_LEAVE_CONNECTED; + + if (dl_ccch_msg.msg.rrc_con_rej.wait_time) { + nas->set_barring(nas_interface_rrc::BARRING_ALL); + mac_timers->timer_get(t302)->set(this, dl_ccch_msg.msg.rrc_con_rej.wait_time*1000); + mac_timers->timer_get(t302)->run(); + } else { + // Perform the actions upon expiry of T302 if wait time is zero + nas->set_barring(nas_interface_rrc::BARRING_NONE); + go_idle = true; + } break; case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP: - rrc_log->info("Connection Setup received\n"); + rrc_log->info("ConnectionSetup received\n"); transaction_id = dl_ccch_msg.msg.rrc_con_setup.rrc_transaction_id; handle_con_setup(&dl_ccch_msg.msg.rrc_con_setup); - rrc_log->info("Notifying NAS of connection setup\n"); - nas->notify_connection_setup(); break; case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST: - rrc_log->info("Connection Reestablishment received\n"); + rrc_log->info("ConnectionReestablishment received\n"); rrc_log->console("Reestablishment OK\n"); transaction_id = dl_ccch_msg.msg.rrc_con_reest.rrc_transaction_id; handle_con_reest(&dl_ccch_msg.msg.rrc_con_reest); break; /* Reception of RRCConnectionReestablishmentReject 5.3.7.8 */ case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ: - rrc_log->info("Connection Reestablishment Reject received\n"); + rrc_log->info("ConnectionReestablishmentReject received\n"); rrc_log->console("Reestablishment Reject\n"); - state = RRC_STATE_LEAVE_CONNECTED; + go_idle = true; break; default: break; @@ -1769,6 +1925,8 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); + security_is_activated = true; + // Configure PDCP for security pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); pdcp->enable_integrity(lcid); @@ -2216,7 +2374,7 @@ void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg } } -void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) { +bool rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) { if (cnfg->phy_cnfg_ded_present) { apply_phy_config_dedicated(&cnfg->phy_cnfg_ded, false); // Apply SR configuration to MAC @@ -2233,7 +2391,15 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) //TODO } if (cnfg->rlf_timers_and_constants_present) { - //TODO + mac_timers->timer_get(t301)->set(this, liblte_rrc_t301_num[cnfg->rlf_timers_and_constants.t301]); + mac_timers->timer_get(t310)->set(this, liblte_rrc_t310_num[cnfg->rlf_timers_and_constants.t310]); + mac_timers->timer_get(t311)->set(this, liblte_rrc_t311_num[cnfg->rlf_timers_and_constants.t311]); + N310 = liblte_rrc_n310_num[cnfg->rlf_timers_and_constants.n310]; + N311 = liblte_rrc_n311_num[cnfg->rlf_timers_and_constants.n311]; + + rrc_log->info("Updated Constants and Timers: N310=%d, N311=%d, t300=%u, t301=%u, t310=%u, t311=%u\n", + N310, N311, mac_timers->timer_get(t300)->get_timeout(), mac_timers->timer_get(t301)->get_timeout(), + mac_timers->timer_get(t310)->get_timeout(), mac_timers->timer_get(t311)->get_timeout()); } for (uint32_t i = 0; i < cnfg->srb_to_add_mod_list_size; i++) { // TODO: handle SRB modification @@ -2246,28 +2412,41 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg) // TODO: handle DRB modification add_drb(&cnfg->drb_to_add_mod_list[i]); } + return true; } void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) { - - // Stop T300 timer - mac_timers->timer_get(t300)->stop(); - // Apply the Radio Resource configuration apply_rr_config_dedicated(&setup->rr_cnfg); + + // Must enter CONNECT before stopping T300 + state = RRC_STATE_CONNECTED; + + rrc_log->console("RRC Connected\n"); + mac_timers->timer_get(t300)->stop(); + mac_timers->timer_get(t302)->stop(); + nas->set_barring(nas_interface_rrc::BARRING_NONE); + + if (dedicatedInfoNAS) { + send_con_setup_complete(dedicatedInfoNAS); + dedicatedInfoNAS = NULL; // deallocated Inside! + } else { + rrc_log->error("Pending to transmit a ConnectionSetupComplete but no dedicatedInfoNAS was in queue\n"); + } } /* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */ void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) { + mac_timers->timer_get(t301)->stop(); - // TODO: Reestablish DRB1. Not done because never was suspended + pdcp->reestablish(); + rlc->reestablish(); // Apply the Radio Resource configuration apply_rr_config_dedicated(&setup->rr_cnfg); - // TODO: Some security stuff here... is it necessary? - + // Send ConnectionSetupComplete message send_con_restablish_complete(); } @@ -2462,11 +2641,15 @@ void rrc::rrc_meas::reset() { filter_k_rsrp = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; filter_k_rsrq = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; - objects.clear(); + + // FIXME: Turn struct into a class and use destructor std::map::iterator iter = active.begin(); while (iter != active.end()) { remove_meas_id(iter++); } + + // These objects do not need destructor + objects.clear(); reports_cfg.clear(); phy->meas_reset(); bzero(&pcell_measurement, sizeof(meas_value_t)); @@ -2491,7 +2674,7 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa // This indicates serving cell if (parent->serving_cell->equals(earfcn, pci)) { - log_h->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); + log_h->debug("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); L3_filter(&pcell_measurement, values); @@ -2503,7 +2686,7 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa // Add to list of neighbour cells bool added = parent->add_neighbour_cell(earfcn, pci, rsrp); - log_h->info("MEAS: New measurement %s earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", + log_h->debug("MEAS: New measurement %s earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", added?"added":"not added", earfcn, pci, rsrp, rsrq, tti); // Only report measurements of 8th strongest cells @@ -2837,7 +3020,7 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) { if (active.count(measId)) { mac_timers->timer_get(active[measId].periodic_timer)->stop(); mac_timers->timer_release_id(active[measId].periodic_timer); - log_h->info("MEAS: Removed measId=%d, timer_id=%d\n", measId, active[measId].periodic_timer); + log_h->info("MEAS: Removed measId=%d\n", measId); active.erase(measId); } else { log_h->warning("MEAS: Removing unexistent measId=%d\n", measId); @@ -2847,14 +3030,14 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) { void rrc::rrc_meas::remove_meas_id(std::map::iterator it) { mac_timers->timer_get(it->second.periodic_timer)->stop(); mac_timers->timer_release_id(it->second.periodic_timer); - log_h->info("MEAS: Removed measId=%d, timer_id=%d\n", it->first, it->second.periodic_timer); + log_h->info("MEAS: Removed measId=%d\n", it->first); active.erase(it); } /* Parses MeasConfig object from RRCConnectionReconfiguration message and applies configuration * as per section 5.5.2 */ -void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) +bool rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) { // Measurement object removal 5.5.2.4 @@ -2987,15 +3170,13 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) } else { is_new = true; active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id(); - if (!active[measId->meas_id].periodic_timer) { - log_h->error("Could not get unique timer id\n"); - } } active[measId->meas_id].object_id = measId->meas_obj_id; active[measId->meas_id].report_id = measId->rep_cnfg_id; - log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, timer_id=%d, nof_values=%zd\n", + log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, timer_id=%u, nof_values=%lu\n", is_new?"Added":"Updated", measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id, - active[measId->meas_id].periodic_timer, active[measId->meas_id].cell_values.size()); + active[measId->meas_id].periodic_timer, + active[measId->meas_id].cell_values.size()); } } @@ -3010,6 +3191,8 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) } update_phy(); + + return true; } /* Instruct PHY to start measurement */ diff --git a/srsue/test/mac/mac_test.cc b/srsue/test/mac/mac_test.cc index 820c4617e..e3d457872 100644 --- a/srsue/test/mac/mac_test.cc +++ b/srsue/test/mac/mac_test.cc @@ -406,13 +406,13 @@ public: printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n", nof_bytes, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period); sib1_decoded = true; - mac.bcch_stop_rx(); + mac.clear_rntis(); } else if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2) { printf("SIB2 received %d bytes\n", nof_bytes); setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy); sib2_decoded = true; - mac.bcch_stop_rx(); + mac.clear_rntis(); } } } diff --git a/srsue/test/phy/ue_itf_test_prach.cc b/srsue/test/phy/ue_itf_test_prach.cc index e161139f9..9ae63d049 100644 --- a/srsue/test/phy/ue_itf_test_prach.cc +++ b/srsue/test/phy/ue_itf_test_prach.cc @@ -380,7 +380,7 @@ int main(int argc, char *argv[]) radio.set_tx_freq(prog_args.rf_tx_freq); // Instruct the PHY to configure PRACH parameters and sync to current cell - while(!my_phy.sync_status()) { + while(!my_phy.cell_is_camping()) { usleep(20000); } diff --git a/srsue/test/phy/ue_itf_test_sib1.cc b/srsue/test/phy/ue_itf_test_sib1.cc index f302fd7aa..bf1f9bbe7 100644 --- a/srsue/test/phy/ue_itf_test_sib1.cc +++ b/srsue/test/phy/ue_itf_test_sib1.cc @@ -196,7 +196,7 @@ int main(int argc, char *argv[]) bool running = true; while(running) { - if (bch_decoded && my_phy.sync_status()) { + if (bch_decoded && my_phy.cell_is_camping()) { uint32_t tti = my_phy.get_current_tti(); // SIB1 is scheduled in subframe #5 of even frames, try to decode next frame SIB1 @@ -206,7 +206,7 @@ int main(int argc, char *argv[]) total_pkts++; } usleep(30000); - if (bch_decoded && my_phy.sync_status() && total_pkts > 0) { + if (bch_decoded && my_phy.cell_is_camping() && total_pkts > 0) { if (srslte_verbose == SRSLTE_VERBOSE_NONE && srsapps_verbose == 0) { float gain = prog_args.rf_gain; if (gain < 0) { diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index 51fc9f83b..91b9c1d24 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -50,6 +50,15 @@ uint8_t auth_request_pdu[] = { 0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0 uint8_t sec_mode_command_pdu[] = { 0x37, 0x37, 0xc7, 0x67, 0xae, 0x00, 0x07, 0x5d, 0x02, 0x01, 0x02, 0xe0, 0x60, 0xc1 }; +uint8_t attach_accept_pdu[] = { 0x27, 0x0f, 0x4f, 0xb3, 0xef, 0x01, 0x07, 0x42, 0x01, 0x3e, + 0x06, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52, + 0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74, + 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, 0x31, + 0x06, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x04, 0x67, 0x70, + 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8, 0x05, 0x02, 0x27, 0x01, + 0x80, 0x50, 0x0b, 0xf6, 0x00, 0xf1, 0x10, 0x80, 0x01, 0x01, + 0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00 }; + uint16 mcc = 61441; uint16 mnc = 65281; @@ -71,18 +80,35 @@ public: class rrc_dummy : public rrc_interface_nas { public: + rrc_dummy() : last_sdu_len(0) { + plmns.plmn_id.mcc = mcc; + plmns.plmn_id.mnc = mnc; + plmns.tac = 0xffff; + } void write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); last_sdu_len = sdu->N_bytes; - srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + //printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + //srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); byte_buffer_pool::get_instance()->deallocate(sdu); } std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); } uint32_t get_last_sdu_len() { return last_sdu_len; } - void plmn_search() {}; - void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, bool con_req) {}; + int plmn_search(srsue::rrc_interface_nas::found_plmn_t* found) { + memcpy(found, &plmns, sizeof(found_plmn_t)); + return 1; + }; + void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {}; + void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) {} + bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, srslte::byte_buffer_t *sdu) { + printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + last_sdu_len = sdu->N_bytes; + srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + byte_buffer_pool::get_instance()->deallocate(sdu); + return true; + } + bool is_connected() {return false;} uint16_t get_mcc() { return mcc; } uint16_t get_mnc() { return mnc; } @@ -90,6 +116,7 @@ public: private: uint32_t last_sdu_len; + found_plmn_t plmns; }; class gw_dummy : public gw_interface_nas, public gw_interface_pdcp @@ -130,15 +157,12 @@ int security_command_test() uint8_t res[16]; usim.init(&args, &usim_log); - srslte::byte_buffer_pool *pool; - pool = byte_buffer_pool::get_instance(); - srsue::nas nas; srslte_nas_config_t cfg; nas.init(&usim, &rrc_dummy, &gw, &nas_log, cfg); // push auth request PDU to NAS to generate security context - byte_buffer_t* tmp = pool->allocate(); + byte_buffer_t* tmp = byte_buffer_pool::get_instance()->allocate(); memcpy(tmp->msg, auth_request_pdu, sizeof(auth_request_pdu)); tmp->N_bytes = sizeof(auth_request_pdu); nas.write_pdu(LCID, tmp); @@ -155,7 +179,7 @@ int security_command_test() ret = SRSLTE_SUCCESS; } - pool->cleanup(); + byte_buffer_pool::get_instance()->cleanup(); return ret; } @@ -190,13 +214,22 @@ int mme_attach_request_test() nas.init(&usim, &rrc_dummy, &gw, &nas_log, nas_cfg); nas.attach_request(); - nas.notify_connection_setup(); - // check length of generated NAS SDU + // this will time out in the first place + + // finally push attach accept + byte_buffer_t* tmp = byte_buffer_pool::get_instance()->allocate(); + memcpy(tmp->msg, attach_accept_pdu, sizeof(attach_accept_pdu)); + tmp->N_bytes = sizeof(attach_accept_pdu); + nas.write_pdu(LCID, tmp); + + // check length of generated NAS SDU (attach complete) if (rrc_dummy.get_last_sdu_len() > 3) { ret = SRSLTE_SUCCESS; } + byte_buffer_pool::get_instance()->cleanup(); + return ret; } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index a3de1a678..7224cf8e3 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -20,7 +20,9 @@ # from antenna to timestamp insertion. # Default "auto". B210 USRP: 100 samples, bladeRF: 27. # burst_preamble_us: Preamble length to transmit before start of burst. -# Default "auto". B210 USRP: 400 us, bladeRF: 0 us. +# Default "auto". B210 USRP: 400 us, bladeRF: 0 us. +# continuous_tx: Transmit samples continuously to the radio or on bursts (auto/yes/no). +# Default is auto (yes for UHD, no for rest) ##################################################################### [rf] dl_earfcn = 3400 @@ -33,6 +35,7 @@ rx_gain = 40 #device_args = auto #time_adv_nsamples = auto #burst_preamble_us = auto +#continuous_tx = auto ##################################################################### @@ -150,7 +153,9 @@ enable = false # sampling frequency offset. Default is enabled. # sss_algorithm: Selects the SSS estimation algorithm. Can choose between # {full, partial, diff}. -# estimator_fil_w: Chooses the coefficients for the 3-tap channel estimator centered filter. +# estimator_fil_auto: The channel estimator smooths the channel estimate with an adaptative filter. +# estimator_fil_stddev: Sets the channel estimator smooth gaussian filter standard deviation. +# estimator_fil_order: Sets the channel estimator smooth gaussian filter order (even values perform better). # The taps are [w, 1-2w, w] # metrics_period_secs: Sets the period at which metrics are requested from the UE. # @@ -204,7 +209,9 @@ enable = false #time_correct_period = 5 #sfo_correct_disable = false #sss_algorithm = full -#estimator_fil_w = 0.1 +#estimator_fil_auto = false +#estimator_fil_stddev = 1.0 +#estimator_fil_order = 4 #average_subframe_enabled = true #sic_pss_enabled = true #pregenerate_signals = false