diff --git a/matlab/tests/equalizer_test.m b/matlab/tests/equalizer_test.m index 80bd16960..ecc3c4cc2 100644 --- a/matlab/tests/equalizer_test.m +++ b/matlab/tests/equalizer_test.m @@ -6,7 +6,7 @@ clear plot_noise_estimation_only=false; -SNR_values_db=20;%linspace(0,30,8); +SNR_values_db=10;%linspace(0,30,8); Nrealizations=1 ; preEVM = zeros(length(SNR_values_db),Nrealizations); @@ -147,7 +147,7 @@ rxWaveform = rxWaveform(1+offset+2:end,:); rxGrid = lteOFDMDemodulate(enb,rxWaveform); rxGrid = rxGrid(:,1:140); -addpath('../../debug/srslte/lib/ch_estimation/test') +addpath('../../build/srslte/lib/ch_estimation/test') %% Channel Estimation [estChannel, noiseEst(snr_idx)] = lteDLChannelEstimate(enb,cec,rxGrid); @@ -156,68 +156,69 @@ snrest_srslte = zeros(10,1); noise_srslte = zeros(10,1); rsrp = zeros(1,10); -for i=0:9 - [d, a, out, snrest_srslte(i+1), noise_srslte(i+1), rsrp(i+1)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid(:,i*14+1:(i+1)*14),[0.1 0.8 0.1],[0.1 0.9],i); - output = [output out]; +[d, ~, out] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid); +output = [output out]; +%RSRP = [RSRP rsrp]; +%meanRSRP(snr_idx)=mean(rsrp); +%SNR_srslte(snr_idx)=mean(snrest_srslte); +%noiseEst_srslte(snr_idx)=mean(noise_srslte); +d=reshape(d, size(estChannel)); +plot(1:288,real(reshape(estChannel(:,11:14),1,[])),'b-',... + 1:288,real(reshape(d(:,11:14),1,[])),'r-') + +% if ~plot_noise_estimation_only +% +% %% MMSE Equalization +% eqGrid_mmse = lteEqualizeMMSE(rxGrid, estChannel, noiseEst(snr_idx)); +% +% eqGrid_srslte = reshape(output,size(eqGrid_mmse)); +% +% % Analysis +% +% %Compute EVM across all input values EVM of pre-equalized receive signal +% preEqualisedEVM = lteEVM(txGrid,rxGrid); +% fprintf('%d-%d: Pre-EQ: %0.3f%%\n', ... +% snr_idx,nreal,preEqualisedEVM.RMS*100); +% +% +% %EVM of post-equalized receive signal +% postEqualisedEVM_mmse = lteEVM(txGrid,reshape(eqGrid_mmse,size(txGrid))); +% fprintf('%d-%d: MMSE: %0.3f%%\n', ... +% snr_idx,nreal,postEqualisedEVM_mmse.RMS*100); +% +% postEqualisedEVM_srslte = lteEVM(txGrid,reshape(eqGrid_srslte,size(txGrid))); +% fprintf('%d-%d: srslte: %0.3f%%\n', ... +% snr_idx,nreal,postEqualisedEVM_srslte.RMS*100); +% +% preEVM(snr_idx,nreal) = preEqualisedEVM.RMS; +% postEVM_mmse(snr_idx,nreal) = mean([postEqualisedEVM_mmse.RMS]); +% postEVM_srslte(snr_idx,nreal) = mean([postEqualisedEVM_srslte.RMS]); +% end end -RSRP = [RSRP rsrp]; -meanRSRP(snr_idx)=mean(rsrp); -SNR_srslte(snr_idx)=mean(snrest_srslte); -noiseEst_srslte(snr_idx)=mean(noise_srslte); - -if ~plot_noise_estimation_only - -%% MMSE Equalization - eqGrid_mmse = lteEqualizeMMSE(rxGrid, estChannel, noiseEst(snr_idx)); - - eqGrid_srslte = reshape(output,size(eqGrid_mmse)); - - % Analysis - - %Compute EVM across all input values EVM of pre-equalized receive signal - preEqualisedEVM = lteEVM(txGrid,rxGrid); - fprintf('%d-%d: Pre-EQ: %0.3f%%\n', ... - snr_idx,nreal,preEqualisedEVM.RMS*100); - - - %EVM of post-equalized receive signal - postEqualisedEVM_mmse = lteEVM(txGrid,reshape(eqGrid_mmse,size(txGrid))); - fprintf('%d-%d: MMSE: %0.3f%%\n', ... - snr_idx,nreal,postEqualisedEVM_mmse.RMS*100); - - postEqualisedEVM_srslte = lteEVM(txGrid,reshape(eqGrid_srslte,size(txGrid))); - fprintf('%d-%d: srslte: %0.3f%%\n', ... - snr_idx,nreal,postEqualisedEVM_srslte.RMS*100); - - preEVM(snr_idx,nreal) = preEqualisedEVM.RMS; - postEVM_mmse(snr_idx,nreal) = mean([postEqualisedEVM_mmse.RMS]); - postEVM_srslte(snr_idx,nreal) = mean([postEqualisedEVM_srslte.RMS]); -end -end -end - -% subplot(1,2,1) - -if ~plot_noise_estimation_only - plot(SNR_values_db, mean(preEVM,2), ... - SNR_values_db, mean(postEVM_mmse,2), ... - SNR_values_db, mean(postEVM_srslte,2)) - legend('No Eq','MMSE-lin','MMSE-srslte') - grid on -end - -% subplot(1,2,2) -if plot_noise_estimation_only - SNR_matlab = 1./(noiseEst*sqrt(2.0)*enb.CellRefP); - - subplot(1,3,1) - plot(SNR_values_db, SNR_values_db, SNR_values_db, 10*log10(SNR_srslte),SNR_values_db, 10*log10(SNR_matlab)) - legend('Theory','srsLTE','Matlab') - - subplot(1,3,2) - plot(SNR_values_db, 10*log10(noiseTx), SNR_values_db, 10*log10(noiseEst_srslte),SNR_values_db, 10*log10(noiseEst)) - legend('Theory','srsLTE','Matlab') - - subplot(1,3,3) - plot(1:10*length(SNR_values_db),RSRP,10*(1:length(SNR_values_db)),meanRSRP) end +% +% % subplot(1,2,1) +% +% if ~plot_noise_estimation_only +% plot(SNR_values_db, mean(preEVM,2), ... +% SNR_values_db, mean(postEVM_mmse,2), ... +% SNR_values_db, mean(postEVM_srslte,2)) +% legend('No Eq','MMSE-lin','MMSE-srslte') +% grid on +% end +% +% % subplot(1,2,2) +% if plot_noise_estimation_only +% SNR_matlab = 1./(noiseEst*sqrt(2.0)*enb.CellRefP); +% +% subplot(1,3,1) +% plot(SNR_values_db, SNR_values_db, SNR_values_db, 10*log10(SNR_srslte),SNR_values_db, 10*log10(SNR_matlab)) +% legend('Theory','srsLTE','Matlab') +% +% subplot(1,3,2) +% plot(SNR_values_db, 10*log10(noiseTx), SNR_values_db, 10*log10(noiseEst_srslte),SNR_values_db, 10*log10(noiseEst)) +% legend('Theory','srsLTE','Matlab') +% +% subplot(1,3,3) +% plot(1:10*length(SNR_values_db),RSRP,10*(1:length(SNR_values_db)),meanRSRP) +% end diff --git a/srsapps/common/include/srsapps/common/params_db.h b/srsapps/common/include/srsapps/common/params_db.h index bfeadff18..61af784a3 100644 --- a/srsapps/common/include/srsapps/common/params_db.h +++ b/srsapps/common/include/srsapps/common/params_db.h @@ -40,12 +40,13 @@ namespace ue { public: params_db(uint32_t nof_params_) { nof_params = nof_params_; - db = (int64_t*) calloc(sizeof(int64_t), nof_params); + db = new int64_t[nof_params]; + for (int i=0;i @@ -226,6 +228,7 @@ public: bool has_space_ce(uint32_t nbytes); bool has_space_sdu(uint32_t nbytes); uint32_t size(); + uint32_t rem_size(); static uint32_t size_plus_header_sdu(uint32_t nbytes); bool update_space_ce(uint32_t nbytes); bool update_space_sdu(uint32_t nbytes); diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h b/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h index e01f1d5a8..da4a0d7ae 100644 --- a/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h +++ b/srsapps/ue/mac/include/srsapps/ue/mac/proc_bsr.h @@ -29,8 +29,11 @@ #include +#include "srsapps/common/log.h" #include "srsapps/ue/mac/proc.h" -#include "srsapps/ue/mac/mux.h" +#include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/mac_io.h" +#include "srsapps/common/timers.h" #ifndef PROCBSR_H #define PROCBSR_H @@ -40,21 +43,53 @@ namespace srslte { namespace ue { -class bsr_proc : public proc +class bsr_proc : public proc, timer_callback { public: bsr_proc(); - void init(log *log_h, mac_params *params_db, mux *mux_unit_); + void init(log *log_h, timers *timers_db, mac_params *params_db, mac_io *mac_io_h); void step(uint32_t tti); void reset(); - void start(); + void setup_lcg(uint32_t lcid, uint32_t new_lcg); + void set_priority(uint32_t lcid, uint32_t priority); + void timer_expired(uint32_t timer_id); + + typedef enum { + LONG_BSR, + SHORT_BSR, + TRUNC_BSR + } bsr_format_t; + + typedef struct { + bsr_format_t format; + uint32_t buff_size[4]; + } bsr_t; + + bool need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t nof_padding_bytes, bsr_t *bsr); + bool need_to_send_sr(); + private: + bool is_pending_sr; mac_params *params_db; - mux *mux_unit; + mac_io *mac_io_h; + timers *timers_db; log *log_h; bool initiated; - + const static int MAX_LCID = 20; + uint32_t lcg[MAX_LCID]; + uint32_t priorities[MAX_LCID]; + uint32_t find_max_priority_lcid(); + enum {NONE, REGULAR, PADDING, PERIODIC} triggered_bsr_type; + bool timer_periodic; + bool timer_retx; + + bsr_t pending_bsr; + bool sr_is_sent; + bool check_all_channels(); + bool check_highest_channel(); + void get_pending_bsr_format(uint32_t nof_padding_bytes); + }; } } diff --git a/srsapps/ue/mac/src/mac.cc b/srsapps/ue/mac/src/mac.cc index 6e2be8919..9bcec72c9 100644 --- a/srsapps/ue/mac/src/mac.cc +++ b/srsapps/ue/mac/src/mac.cc @@ -47,7 +47,8 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_) tti = 0; is_synchronized = false; - mux_unit.init(log_h, &mac_io_lch); + bsr_procedure.init(log_h, &timers_db, ¶ms_db, &mac_io_lch); + mux_unit.init(log_h, &mac_io_lch, &bsr_procedure); demux_unit.init(phy_h, log_h, &mac_io_lch, &timers_db); ra_procedure.init(¶ms_db, phy_h, log_h, &timers_db, &mux_unit, &demux_unit); sr_procedure.init(log_h, ¶ms_db, phy_h); @@ -173,17 +174,23 @@ void mac::main_radio_loop() { log_h->step(tti); // Step all procedures - ra_procedure.step(tti); - //sr_procedure.step(tti); - //bsr_procedure.step(tti); - //phr_procedure.step(tti); + bsr_procedure.step(tti); + + // Check if BSR procedure need to start SR + if (bsr_procedure.need_to_send_sr()) { + sr_procedure.start(); + } + 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); + + + //phr_procedure.step(tti); // Receive PCH, if requested receive_pch(tti); @@ -216,13 +223,7 @@ void mac::main_radio_loop() { Info("Starting RA procedure by RLC order\n"); ra_procedure.start_rlc_order(); } - } /*else if (mux_unit.is_pending_any_sdu()) { - // Sart SR if no PUSCH resources available for TTI+4 - if (!ul_resources_available) { - sr_procedure.start(); - Info("Starting Scheduling Request procedure\n"); - } - }*/ + } } } } @@ -511,13 +512,11 @@ void mac::set_param(mac_params::mac_param_t param, int64_t value) params_db.set_param((uint32_t) param, value); } -void mac::set_dcch0_priority(uint32_t priority, int PBR_x_tti, uint32_t BSD) -{ - mux_unit.set_priority(mac_io::MAC_LCH_DCCH0_UL - mac_io::MAC_LCH_CCCH_UL, priority, PBR_x_tti, BSD); -} -void mac::set_dtch0_priority(uint32_t priority, int PBR_x_tti, uint32_t BSD) +void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) { - mux_unit.set_priority(mac_io::MAC_LCH_DTCH0_UL - mac_io::MAC_LCH_CCCH_UL, priority, PBR_x_tti, BSD); + mux_unit.set_priority(mac_io::MAC_LCH_CCCH_UL+lcid, priority, PBR_x_tti, BSD); + bsr_procedure.setup_lcg(lcid, lcg); + bsr_procedure.set_priority(lcid, priority); } diff --git a/srsapps/ue/mac/src/mux.cc b/srsapps/ue/mac/src/mux.cc index fcda7d6ec..bbab90c9a 100644 --- a/srsapps/ue/mac/src/mux.cc +++ b/srsapps/ue/mac/src/mux.cc @@ -52,10 +52,11 @@ mux::mux() : pdu_msg(20) } } -void mux::init(log *log_h_, mac_io *mac_io_h_) +void mux::init(log *log_h_, mac_io *mac_io_h_, bsr_proc *bsr_procedure_) { log_h = log_h_; mac_io_h = mac_io_h_; + bsr_procedure = bsr_procedure_; } void mux::reset() @@ -65,6 +66,11 @@ void mux::reset() } } +bool mux::is_pending_ccch_sdu() +{ + return is_pending_sdu(0); +} + bool mux::is_pending_any_sdu() { for (int i=0;iget(mac_io::MAC_LCH_CCCH_UL)->isempty(); +bool mux::is_pending_sdu(uint32_t lch_id) { + lch_id += (uint32_t) mac_io::MAC_LCH_CCCH_UL; + if (lch_id < mac_io::MAC_NOF_QUEUES) { + return !mac_io_h->get(lch_id)->isempty(); + } } void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD) @@ -159,6 +167,18 @@ void mux::append_crnti_ce_next_tx(uint16_t crnti) { pending_crnti_ce = crnti; } +sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) { + switch(format) { + case bsr_proc::LONG_BSR: + return sch_subh::LONG_BSR; + case bsr_proc::SHORT_BSR: + return sch_subh::SHORT_BSR; + case bsr_proc::TRUNC_BSR: + return sch_subh::TRUNC_BSR; + + } +} + bool mux::assemble_pdu(uint32_t pdu_sz_nbits) { uint8_t *buff = (uint8_t*) pdu_buff.request(); @@ -203,8 +223,15 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) { } pending_crnti_ce = 0; + bsr_proc::bsr_t bsr; + bool send_bsr_normal = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_sz_nbits/8, 0, &bsr); + // MAC control element for BSR, with exception of BSR included for padding; - // TODO + if (send_bsr_normal) { + pdu_msg.next(); + pdu_msg.get()->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format)); + } + // MAC control element for PHR // TODO @@ -226,8 +253,12 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) { } // MAC control element for BSR included for padding. - // TODO - + bool send_bsr_padding = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_sz_nbits/8, pdu_msg.rem_size(), &bsr); + if (send_bsr_padding) { + pdu_msg.next(); + pdu_msg.get()->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format)); + } + pthread_mutex_unlock(&mutex); /* Release all SDUs */ @@ -249,12 +280,10 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) { return true; } - bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg) { return allocate_sdu(lcid, pdu_msg, NULL); } - bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz) { @@ -263,6 +292,9 @@ bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz) uint8_t *buff_ptr = (uint8_t*) mac_io_h->get(mac_io::MAC_LCH_CCCH_UL + lcid)->pop(&buff_len, nof_tx_pkts[lcid]); if (buff_ptr) { // there is pending SDU to allocate + if (sdu_sz) { + *sdu_sz = buff_len; + } if (pdu_msg->new_subh()) { // there is space for a new subheader pdu_msg->next(); if (pdu_msg->get()->set_sdu(lcid, buff_ptr, buff_len/8)) { // new SDU could be added diff --git a/srsapps/ue/mac/src/pdu.cc b/srsapps/ue/mac/src/pdu.cc index 54a703490..80b15514c 100644 --- a/srsapps/ue/mac/src/pdu.cc +++ b/srsapps/ue/mac/src/pdu.cc @@ -132,6 +132,9 @@ bool sch_pdu::write_packet(uint8_t* ptr) } +uint32_t sch_pdu::rem_size() { + return rem_len; +} uint32_t sch_pdu::size() { @@ -175,8 +178,6 @@ bool sch_pdu::update_space_sdu(uint32_t nbytes) } } - - void sch_subh::init() { lcid = 0; @@ -242,19 +243,33 @@ bool sch_subh::is_sdu() } uint16_t sch_subh::get_c_rnti() { - return *((uint16_t*) ce_payload); + uint8_t *ptr = ce_payload; + uint16_t ret = (uint16_t) srslte_bit_unpack(&ptr, 16); + return ret; } uint64_t sch_subh::get_con_res_id() { - return *((uint64_t*) ce_payload); + uint8_t *ptr = ce_payload; + uint64_t ret = (uint64_t) srslte_bit_unpack_l(&ptr, 48); + return ret; } uint8_t sch_subh::get_phd() { - return *((uint8_t*) ce_payload); + uint8_t *ptr = ce_payload; + ptr += 2; + uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6); + return ret; +} +uint8_t sch_subh::get_ta_cmd() +{ + uint8_t *ptr = ce_payload; + ptr += 2; + uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6); + return ret; } uint32_t sch_subh::get_sdu_lcid() { - return *((uint32_t*) ce_payload); + return lcid; } uint32_t sch_subh::get_sdu_nbytes() { @@ -264,19 +279,46 @@ uint8_t* sch_subh::get_sdu_ptr() { return sdu_payload_ptr; } -uint8_t sch_subh::get_ta_cmd() -{ - return *((uint8_t*) ce_payload); -} void sch_subh::set_padding() { lcid = PADDING; } + +bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format) +{ + uint32_t nonzero_lcg=0; + for (int i=0;i<4;i++) { + if (buff_size[i]) { + nonzero_lcg=i; + } + } + uint32_t ce_size = format==LONG_BSR?3:1; + if (((sch_pdu*)parent)->has_space_ce(ce_size)) { + uint8_t *ptr = ce_payload; + if (format==LONG_BSR) { + for (int i=0;i<4;i++) { + srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6); + } + } else { + srslte_bit_pack(nonzero_lcg, &ptr, 2); + srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6); + } + lcid = format; + ((sch_pdu*)parent)->update_space_ce(ce_size); + return true; + } else { + return false; + } +} + bool sch_subh::set_c_rnti(uint16_t crnti) { if (((sch_pdu*)parent)->has_space_ce(2)) { + *((uint16_t*) ce_payload) = crnti; lcid = C_RNTI; + uint8_t *ptr = ce_payload; + srslte_bit_pack(crnti, &ptr, 16); ((sch_pdu*)parent)->update_space_ce(2); return true; } else { @@ -286,7 +328,8 @@ bool sch_subh::set_c_rnti(uint16_t crnti) bool sch_subh::set_con_res_id(uint64_t con_res_id) { if (((sch_pdu*)parent)->has_space_ce(6)) { - *((uint64_t*) ce_payload) = con_res_id; + uint8_t *ptr = ce_payload; + srslte_bit_pack_l(con_res_id, &ptr, 48); lcid = CON_RES_ID; ((sch_pdu*)parent)->update_space_ce(6); return true; @@ -297,7 +340,9 @@ bool sch_subh::set_con_res_id(uint64_t con_res_id) bool sch_subh::set_phd(uint8_t phd) { if (((sch_pdu*)parent)->has_space_ce(1)) { - *((uint8_t*) ce_payload) = phd; + uint8_t *ptr = ce_payload; + srslte_bit_pack(0, &ptr, 2); + srslte_bit_pack(phd, &ptr, 6); lcid = PHD_REPORT; ((sch_pdu*)parent)->update_space_ce(1); return true; @@ -320,7 +365,9 @@ bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_) bool sch_subh::set_ta_cmd(uint8_t ta_cmd) { if (((sch_pdu*)parent)->has_space_ce(1)) { - *((uint8_t*) ce_payload) = ta_cmd; + uint8_t *ptr = ce_payload; + srslte_bit_pack(0, &ptr, 2); + srslte_bit_pack(ta_cmd, &ptr, 6); lcid = TA_CMD; ((sch_pdu*)parent)->update_space_ce(1); return true; @@ -351,13 +398,13 @@ void sch_subh::write_subheader(uint8_t** ptr, bool is_last) } void sch_subh::write_payload(uint8_t** ptr) { + uint8_t *src; if (is_sdu()) { - memcpy(*ptr, sdu_payload_ptr, nof_bytes*8*sizeof(uint8_t)); + src = sdu_payload_ptr; } else { - for (int i=0;i 150000) { + return 63; + } else { + for (int i=0;i<61;i++) { + if (buffer_size > btable[i]) { + return 1+i; + } + } + return 62; + } +} } diff --git a/srsapps/ue/mac/src/proc_bsr.cc b/srsapps/ue/mac/src/proc_bsr.cc index 3583793b8..8d379d1f9 100644 --- a/srsapps/ue/mac/src/proc_bsr.cc +++ b/srsapps/ue/mac/src/proc_bsr.cc @@ -27,6 +27,8 @@ #include "srsapps/ue/mac/proc_bsr.h" #include "srsapps/ue/mac/mac_params.h" +#include "srsapps/ue/mac/mac.h" +#include "srsapps/ue/mac/mux.h" namespace srslte { namespace ue { @@ -34,31 +36,245 @@ namespace srslte { bsr_proc::bsr_proc() { initiated = false; + timer_periodic = false; + timer_retx = false; + for (int i=0;iget(i)->pending_data(); + if (pending_data > 0) { + lcg_with_data = group; + } + } + } + } + + if (pending_data) { + // If no data is available belonging to any of the logical channels belonging to any other LCG + for (uint32_t group=0;group<4 && trigger_bsr;group++) { + if (group != lcg_with_data) { + for (int i=0;iget(i)->pending_data() && priorities[i] > min_priority_group[group]) { + trigger_bsr=false; + } + } + } + } + } + } + + return trigger_bsr; +} +bool bsr_proc::check_all_channels() { + bool ret = false; + bzero(&pending_bsr, sizeof(bsr_t)); + for (int i=0;iNOF_UL_LCH;i++) { + uint32_t n = mac_io_h->get(i)->pending_data(); + pending_bsr.buff_size[lcg[i]] += n; + if (n > 0) { + ret = true; + } + } + return ret; +} + +void bsr_proc::get_pending_bsr_format(uint32_t nof_padding_bytes) { + uint32_t nof_lcg=0; + for (int i=0;i<4;i++) { + if (pending_bsr.buff_size[i] > 0) { + nof_lcg++; + } + } + if (triggered_bsr_type == PADDING) { + if (nof_padding_bytes < 4) { + // If space only for short + if (nof_lcg > 1) { + pending_bsr.format = TRUNC_BSR; + uint32_t max_prio_ch = find_max_priority_lcid(); + for (int i=0;i<4;i++) { + if (lcg[max_prio_ch] != i) { + pending_bsr.buff_size[i] = 0; + } + } + } else { + pending_bsr.format = SHORT_BSR; + } + } else { + // If space for long BSR + pending_bsr.format = LONG_BSR; + } + } else { + pending_bsr.format = SHORT_BSR; + if (nof_lcg > 1) { + pending_bsr.format = LONG_BSR; + } + } } + +// Checks if Regular BSR must be assembled, as defined in 5.4.5 +// Padding BSR is assembled when called by mux_unit when UL grant is received +// Periodic BSR is triggered by the expiration of the timers void bsr_proc::step(uint32_t tti) { if (!initiated) { return; } + + if (!timer_periodic) { + if (params_db->get_param(mac_params::BSR_TIMER_PERIODIC)) { + timer_periodic = true; + timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, params_db->get_param(mac_params::BSR_TIMER_PERIODIC)); + } + } + + if (!timer_retx) { + if (params_db->get_param(mac_params::BSR_TIMER_RETX)) { + timer_retx = true; + timers_db->get(mac::BSR_TIMER_RETX)->set(this, params_db->get_param(mac_params::BSR_TIMER_RETX)); + } + } + + // Check condition 1 in Sec 5.4.5 + if (triggered_bsr_type == NONE) { + if (check_highest_channel()) { + triggered_bsr_type = REGULAR; + } + } } - + +bool bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t nof_padding_bytes, bsr_t *bsr) +{ + bool ret = false; + + if (triggered_bsr_type == NONE) { + // If enough space for at least truncated BSR + if (nof_padding_bytes >= 2) { + // Check condition 2 in Sec 5.4.5 + if (check_all_channels()) { + triggered_bsr_type = PADDING; + } + } + } + if (triggered_bsr_type != NONE) { + // If no more data is pending and there is no space for MAC CE + uint32_t nof_pending_bytes = 0; + for (int i=0;i<4;i++) { + nof_pending_bytes += pending_bsr.buff_size[i]; + } + // Do not include BSR CE if the UL grant can accomodate all pending data but is not sufficient + // to additionally accomodate the BSR MAC CE plus its header + uint32_t bsr_sz_plus_header = 1 + pending_bsr.format == LONG_BSR?3:1; + if (nof_pending_bytes + bsr_sz_plus_header == nof_grant_bytes) { + // if nof_pending_bytes + bsr_sz_plus_header > nof_grant_bytes, BSR has higher priority than data + return false; + } + + get_pending_bsr_format(nof_padding_bytes); + + // Instruct MUX unit to generate MAC CE + ret = true; + memcpy(bsr, &pending_bsr, sizeof(bsr_t)); + if (timer_periodic && pending_bsr.format != TRUNC_BSR) { + timers_db->get(mac::BSR_TIMER_PERIODIC)->reset(); + timers_db->get(mac::BSR_TIMER_PERIODIC)->run(); + } + // Cancel all triggered BSR + triggered_bsr_type = NONE; + } + + // Restart or Start ReTX timer + if (timer_retx) { + timers_db->get(mac::BSR_TIMER_RETX)->reset(); + timers_db->get(mac::BSR_TIMER_RETX)->run(); + } + return ret; +} + +bool bsr_proc::need_to_send_sr() { + if (!sr_is_sent && triggered_bsr_type == REGULAR) { + sr_is_sent = true; + return true; + } + return false; +} + +void bsr_proc::setup_lcg(uint32_t lcid, uint32_t new_lcg) +{ + if (lcid < MAX_LCID && new_lcg < 4) { + lcg[lcid] = new_lcg; + } +} + +void bsr_proc::set_priority(uint32_t lcid, uint32_t priority) { + if (lcid < MAX_LCID) { + priorities[lcid] = priority; } } + +uint32_t bsr_proc::find_max_priority_lcid() { + uint32_t max_prio = 0, max_idx = 0; + for (int i=0;i max_prio) { + max_prio = priorities[i]; + max_idx = i; + } + } + return max_idx; +} + +} +} diff --git a/srsapps/ue/mac/test/CMakeLists.txt b/srsapps/ue/mac/test/CMakeLists.txt index 9b3c92b00..ec65de6fc 100644 --- a/srsapps/ue/mac/test/CMakeLists.txt +++ b/srsapps/ue/mac/test/CMakeLists.txt @@ -24,5 +24,5 @@ FIND_PACKAGE(openLTE) IF(UHD_FOUND AND OPENLTE_FOUND) INCLUDE_DIRECTORIES(${OPENLTE_INCLUDE_DIRS}) ADD_EXECUTABLE(mac_test mac_test.cc) - TARGET_LINK_LIBRARIES(mac_test srsapps_ue_mac srsapps_ue_phy srsapps_common srsapps_radio srslte ${OPENLTE_LIBRARIES} srslte_uhd) + TARGET_LINK_LIBRARIES(mac_test srsapps_ue_mac srsapps_ue_phy srsapps_radio srslte ${OPENLTE_LIBRARIES} srslte_uhd) ENDIF(UHD_FOUND AND OPENLTE_FOUND) diff --git a/srsapps/ue/phy/include/srsapps/ue/phy/phy.h b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h index 53174b1ba..1f769a0a6 100644 --- a/srsapps/ue/phy/include/srsapps/ue/phy/phy.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h @@ -63,12 +63,8 @@ typedef _Complex float cf_t; class phy { public: - phy() { - started = false; - is_sfn_synched = false; - cell_is_set = false; - phy_state = IDLE; - } + phy(); + void set(); bool init(radio *radio_handler, tti_sync *ttisync, log *log_h); bool init_agc(radio *radio_handler, tti_sync *ttisync, log *log_h); void stop(); @@ -134,7 +130,7 @@ private: srslte_cell_t cell; bool cell_is_set; bool is_sfn_synched; - bool started; + volatile bool started; srslte_ue_sync_t ue_sync; srslte_ue_mib_t ue_mib; diff --git a/srsapps/ue/phy/src/phy.cc b/srsapps/ue/phy/src/phy.cc index 6632684a2..237e53326 100644 --- a/srsapps/ue/phy/src/phy.cc +++ b/srsapps/ue/phy/src/phy.cc @@ -41,6 +41,14 @@ namespace srslte { namespace ue { +phy::phy() +{ + started = false; + is_sfn_synched = false; + cell_is_set = false; + phy_state = IDLE; +} + bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h) { return init_(radio_handler_, ttisync_, log_h, false); } diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index a300eb30d..9f919a4a3 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -643,14 +643,15 @@ void *plot_thread_run(void *arg) { tmp_plot[i] = -80; } } - for (i = 0; i < SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0); i++) { - tmp_plot2[i] = 20 * log10f(cabsf(ue_dl.chest.pilot_estimates_average[0][i])); + for (i = 0; i < 4*12*ue_dl.cell.nof_prb; i++) { + tmp_plot2[i] = 20 * log10f(cabsf(ue_dl.ce[0][i])); if (isinf(tmp_plot2[i])) { tmp_plot2[i] = -80; } } - plot_real_setNewData(&pce, tmp_plot2, SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0)); + plot_real_setNewData(&pce, tmp_plot2, 4*12*ue_dl.cell.nof_prb); + if (!prog_args.input_file_name) { int max = srslte_vec_max_fi(ue_sync.strack.pss.conv_output_avg, ue_sync.strack.pss.frame_size+ue_sync.strack.pss.fft_size-1); srslte_vec_sc_prod_fff(ue_sync.strack.pss.conv_output_avg, @@ -662,10 +663,10 @@ void *plot_thread_run(void *arg) { } #ifdef PLOT_CHEST_ARGUMENT - for (i = 0; i < SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0); i++) { - tmp_plot2[i] = cargf(ue_dl.chest.pilot_estimates_average[0][i]); + for (i = 0; i < 2*12*ue_dl.cell.nof_prb; i++) { + tmp_plot2[i] = cargf(ue_dl.ce[0][i]); } - plot_real_setNewData(&pce_arg, tmp_plot2, SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0)); + plot_real_setNewData(&pce_arg, tmp_plot2, 2*12*ue_dl.cell.nof_prb); #endif plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce); diff --git a/srslte/include/srslte/ch_estimation/chest_dl.h b/srslte/include/srslte/ch_estimation/chest_dl.h index 36e9ab789..d6b0a9158 100644 --- a/srslte/include/srslte/ch_estimation/chest_dl.h +++ b/srslte/include/srslte/ch_estimation/chest_dl.h @@ -50,8 +50,8 @@ #include "srslte/ch_estimation/refsignal_dl.h" #include "srslte/common/phy_common.h" -#define SRSLTE_CHEST_MAX_FILTER_FREQ_LEN 10 -#define SRSLTE_CHEST_MAX_FILTER_TIME_LEN 4 +#define SRSLTE_CHEST_MAX_FILTER_FREQ_LEN 21 +#define SRSLTE_CHEST_MAX_FILTER_TIME_LEN 40 typedef struct { srslte_cell_t cell; diff --git a/srslte/include/srslte/utils/bit.h b/srslte/include/srslte/utils/bit.h index 713866b7e..78341da73 100644 --- a/srslte/include/srslte/utils/bit.h +++ b/srslte/include/srslte/utils/bit.h @@ -52,6 +52,13 @@ SRSLTE_API void srslte_bit_unpack_vector(uint8_t *bits_packed, SRSLTE_API uint32_t srslte_bit_unpack(uint8_t **bits, int nof_bits); +SRSLTE_API uint64_t srslte_bit_unpack_l(uint8_t **bits, + int nof_bits); + +SRSLTE_API void srslte_bit_pack_l(uint64_t value, + uint8_t **bits, + int nof_bits); + SRSLTE_API void srslte_bit_pack(uint32_t value, uint8_t **bits, int nof_bits); diff --git a/srslte/lib/ch_estimation/src/chest_dl.c b/srslte/lib/ch_estimation/src/chest_dl.c index 9781ff334..bc0fe130f 100644 --- a/srslte/lib/ch_estimation/src/chest_dl.c +++ b/srslte/lib/ch_estimation/src/chest_dl.c @@ -40,11 +40,32 @@ #include "srslte/utils/vector.h" #include "srslte/utils/convolution.h" -#define CHEST_RS_AVERAGE_TIME 2 -#define CHEST_RS_AVERAGE_FREQ 3 - #define NOISE_POWER_METHOD 1 // 0: Difference between noisy received and noiseless; 1: power of empty subcarriers +#define DEFAULT_FILTER_FREQ_LEN 11 // Must be odd +#define DEFAULT_FILTER_TIME_LEN 3 + +static void init_default_filters(srslte_chest_dl_t *q) { + + float f[DEFAULT_FILTER_FREQ_LEN]; + float t[DEFAULT_FILTER_TIME_LEN]; + + for (int i=0;itmp_freqavg = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); + q->tmp_freqavg = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!q->tmp_freqavg) { perror("malloc"); goto clean_exit; } - q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * 2 * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); + q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!q->tmp_noise) { perror("malloc"); goto clean_exit; } - for (int i=0;itmp_timeavg[i] = srslte_vec_malloc(sizeof(cf_t) * 2*cell.nof_prb); - if (!q->tmp_timeavg[i]) { - perror("malloc"); - goto clean_exit; - } - bzero(q->tmp_timeavg[i], sizeof(cf_t) * 2*cell.nof_prb); - } - q->tmp_timeavg_mult = srslte_vec_malloc(sizeof(cf_t) * 2*cell.nof_prb); + q->tmp_timeavg_mult = srslte_vec_malloc(sizeof(cf_t) * 12*cell.nof_prb); if (!q->tmp_timeavg_mult) { perror("malloc"); goto clean_exit; } for (int i=0;ipilot_estimates[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i)); + q->pilot_estimates[i] = srslte_vec_malloc(2*sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i)); if (!q->pilot_estimates[i]) { perror("malloc"); goto clean_exit; } - // FIXME: There's an invalid read during rsrp estimation for this buffer - q->pilot_estimates_average[i] = srslte_vec_malloc(2 * sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i)); - if (!q->pilot_estimates_average[i]) { - perror("malloc"); - goto clean_exit; - } q->pilot_recv_signal[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i)); if (!q->pilot_recv_signal[i]) { perror("malloc"); @@ -122,15 +129,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell) goto clean_exit; } - /* Set default time/freq filters */ - //float f[3]={0.2, 0.6, 0.2}; - //srslte_chest_dl_set_filter_freq(q, f, 3); - - float f[9]={0.025, 0.075, 0.05, 0.15, 0.4, 0.15, 0.05, 0.075, 0.025}; - srslte_chest_dl_set_filter_freq(q, f, 9); - - //srslte_chest_dl_set_filter_time_ema(q, 0.8); - + init_default_filters(q); q->cell = cell; } @@ -153,11 +152,6 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q) if (q->tmp_noise) { free(q->tmp_noise); } - for (int i=0;itmp_timeavg[i]) { - free(q->tmp_timeavg[i]); - } - } if (q->tmp_timeavg_mult) { free(q->tmp_timeavg_mult); } @@ -168,9 +162,6 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q) if (q->pilot_estimates[i]) { free(q->pilot_estimates[i]); } - if (q->pilot_estimates_average[i]) { - free(q->pilot_estimates_average[i]); - } if (q->pilot_recv_signal[i]) { free(q->pilot_recv_signal[i]); } @@ -209,14 +200,11 @@ int srslte_chest_dl_set_filter_time(srslte_chest_dl_t *q, float *filter, uint32_ #if NOISE_POWER_METHOD==0 - /* Uses the difference between the averaged and non-averaged pilot estimates */ -static float estimate_noise_port(srslte_chest_dl_t *q, uint32_t port_id, cf_t *avg_pilots) { +static float estimate_noise_port(srslte_chest_dl_t *q, cf_t *average, cf_t *ce, uint32_t len) { /* Use difference between averaged and noisy LS pilot estimates */ - srslte_vec_sub_ccc(avg_pilots, q->pilot_estimates[port_id], - q->tmp_noise, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); - - return srslte_vec_avg_power_cf(q->tmp_noise, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); + srslte_vec_sub_ccc(average, ce, q->tmp_noise, len); + return srslte_vec_avg_power_cf(q->tmp_noise, len); } #endif @@ -236,97 +224,52 @@ static float estimate_noise_port(srslte_chest_dl_t *q, cf_t *input) { } #endif -#define pilot_est(idx) q->pilot_estimates[port_id][SRSLTE_REFSIGNAL_PILOT_IDX(idx,l,q->cell)] -#define pilot_avg(idx) q->pilot_estimates_average[port_id][SRSLTE_REFSIGNAL_PILOT_IDX(idx,l,q->cell)] -#define pilot_tmp(idx) q->tmp_freqavg[SRSLTE_REFSIGNAL_PILOT_IDX(idx,l,q->cell)] -static void average_pilots(srslte_chest_dl_t *q, uint32_t port_id) +static void average_estimates(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id) { - int nref=2*q->cell.nof_prb; + int nref=12*q->cell.nof_prb; uint32_t l, i; /* For each symbol with pilots in a slot */ - for (l=0;lcell.cp);l++) { if (q->filter_freq_len > 0) { /* Filter pilot estimates in frequency */ - srslte_conv_same_cf(&pilot_est(0), q->filter_freq, &pilot_tmp(0), nref, q->filter_freq_len); - - /* Adjust extremes using linear interpolation */ - - pilot_tmp(0) += srslte_interp_linear_onesample(pilot_est(1), pilot_est(0)) - * q->filter_freq[q->filter_freq_len/2-1]*1.2; - pilot_tmp(nref-1) += srslte_interp_linear_onesample(pilot_est(nref-2), pilot_est(nref-1)) - * q->filter_freq[q->filter_freq_len/2+1]*1.2; + srslte_conv_same_cf(&ce[l*12*q->cell.nof_prb], q->filter_freq, &q->tmp_freqavg[l*12*q->cell.nof_prb], nref, q->filter_freq_len); } else { - memcpy(&pilot_tmp(0), &pilot_est(0), nref * sizeof(cf_t)); + memcpy(&q->tmp_freqavg[l*12*q->cell.nof_prb], &ce[l*12*q->cell.nof_prb], nref * sizeof(cf_t)); } } #if NOISE_POWER_METHOD==0 - q->noise_estimate[port_id] = estimate_noise_port(q, port_id, q->tmp_freqavg); + q->noise_estimate[port_id] = estimate_noise_port(q, q->tmp_freqavg, ce, + SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); #endif - -//#define EMA_VEC - - /* Filter with Exponential moving average (IIR) */ - if (q->filter_time_ema > 0) { -#ifdef EMA_VEC - srslte_vec_ema_filter(&q->tmp_freqavg[0], - &q->pilot_estimates_average[port_id][2*q->cell.nof_prb*srslte_refsignal_cs_nof_symbols(port_id)], - &q->pilot_estimates_average[port_id][0], - q->filter_time_ema, - nref); - for (l=1;ltmp_freqavg[2*q->cell.nof_prb*l], - &q->pilot_estimates_average[port_id][2*q->cell.nof_prb*(l-1)], - &q->pilot_estimates_average[port_id][2*q->cell.nof_prb*l], - q->filter_time_ema, - nref); - } -#else - for (i=0;ipilot_estimates_average[port_id][ - SRSLTE_REFSIGNAL_PILOT_IDX(i,srslte_refsignal_cs_nof_symbols(port_id),q->cell)], q->filter_time_ema); - for (l=1;lpilot_estimates_average[port_id][SRSLTE_REFSIGNAL_PILOT_IDX(i,l-1,q->cell)], q->filter_time_ema); - } - } -#endif - - } else { - /* Filter with FIR or don't filter */ - for (l=0;lfilter_time_len > 0) { - /* Move last symbols */ - for (i=0;ifilter_time_len-1;i++) { - memcpy(q->tmp_timeavg[i], q->tmp_timeavg[i+1], nref*sizeof(cf_t)); - } - /* Save last symbol to buffer */ - memcpy(q->tmp_timeavg[q->filter_time_len-1], &pilot_tmp(0), nref*sizeof(cf_t)); - - /* Multiply all symbols by filter and add them */ - if (l > 0) { - bzero(&pilot_avg(0), nref * sizeof(cf_t)); - for (i=0;ifilter_time_len;i++) { - srslte_vec_sc_prod_cfc(q->tmp_timeavg[i], q->filter_time[i], q->tmp_timeavg_mult, nref); - srslte_vec_sum_ccc(q->tmp_timeavg_mult, &pilot_avg(0), &pilot_avg(0), nref); - } + /* Filter with FIR or don't filter */ + for (l=0;lcell.cp);l++) { + /* Filter in time domain. */ + if (q->filter_time_len > 0) { + /* Multiply symbols by filter and add them */ + bzero(&ce[l*12*q->cell.nof_prb], nref * sizeof(cf_t)); + for (i=0;ifilter_time_len;i++) { + if (l+i-q->filter_time_len/2 < SRSLTE_CP_NSYMB(q->cell.cp) && l+i-q->filter_time_len/2 > 0) { + srslte_vec_sc_prod_cfc(&q->tmp_freqavg[(l+i-q->filter_time_len/2)*12*q->cell.nof_prb], q->filter_time[i], q->tmp_timeavg_mult, nref); + srslte_vec_sum_ccc(q->tmp_timeavg_mult, &ce[l*12*q->cell.nof_prb], &ce[l*12*q->cell.nof_prb], nref); } else { - memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t)); + srslte_vec_sc_prod_cfc(&q->tmp_freqavg[l*12*q->cell.nof_prb], q->filter_time[i], q->tmp_timeavg_mult, nref); + srslte_vec_sum_ccc(q->tmp_timeavg_mult, &ce[l*12*q->cell.nof_prb], &ce[l*12*q->cell.nof_prb], nref); } - } else { - memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t)); - } - } + } + } else { + memcpy(&ce[l*12*q->cell.nof_prb], &q->tmp_freqavg[l*12*q->cell.nof_prb], nref * sizeof(cf_t)); + } } } + #define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)] -static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id) +static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id) { /* interpolate the symbols with references in the freq domain */ uint32_t l; @@ -335,7 +278,7 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id) /* Interpolate in the frequency domain */ for (l=0;lcell, l, port_id, 0); - srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_avg(0), + srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l], &ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE], fidx_offset, SRSLTE_NRE/2-fidx_offset); } @@ -399,8 +342,13 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u srslte_vec_prod_conj_ccc(q->pilot_recv_signal[port_id], q->csr_signal.pilots[port_id/2][sf_idx], q->pilot_estimates[port_id], SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); - /* Average pilot estimates */ - average_pilots(q, port_id); + if (ce != NULL) { + /* Interpolate to create channel estimates for all resource grid */ + interpolate_pilots(q, q->pilot_estimates[port_id], ce, port_id); + + /* Average channel estimates */ + average_estimates(q, ce, port_id); + } #if NOISE_POWER_METHOD==1 q->noise_estimate[port_id] = estimate_noise_port(q, input); @@ -413,11 +361,6 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u q->rssi[port_id] = srslte_chest_dl_rssi(q, input, port_id); } - /* Interpolate to create channel estimates for all resource grid */ - if (ce != NULL) { - interpolate_pilots(q, ce, port_id); - } - return 0; } diff --git a/srslte/lib/ch_estimation/test/chest_test_dl.c b/srslte/lib/ch_estimation/test/chest_test_dl.c index efbc6b213..71d10b739 100644 --- a/srslte/lib/ch_estimation/test/chest_test_dl.c +++ b/srslte/lib/ch_estimation/test/chest_test_dl.c @@ -201,7 +201,7 @@ int main(int argc, char **argv) { mse /= num_re; printf("MSE: %f\n", mse); - if (mse > 1.7) { + if (mse > 2.0) { goto do_exit; } diff --git a/srslte/lib/ch_estimation/test/chest_test_dl_mex.c b/srslte/lib/ch_estimation/test/chest_test_dl_mex.c index cfbed897c..7383359f2 100644 --- a/srslte/lib/ch_estimation/test/chest_test_dl_mex.c +++ b/srslte/lib/ch_estimation/test/chest_test_dl_mex.c @@ -72,11 +72,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) double *outr1=NULL, *outi1=NULL; double *outr2=NULL, *outi2=NULL; - if (nrhs < NOF_INPUTS) { - help(); - return; - } - if (!mxIsDouble(CELLID) && mxGetN(CELLID) != 1 && !mxIsDouble(PORTS) && mxGetN(PORTS) != 1 && mxGetM(CELLID) != 1) { @@ -117,34 +112,30 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } sf_idx = (uint32_t) *((double*) mxGetPr(SFIDX)); - } else { - if (nrhs != NOF_INPUTS) { - help(); - return; - } - } - - uint32_t filter_len = 0; - float *filter; - double *f; + } - filter_len = mxGetNumberOfElements(FREQ_FILTER); - filter = malloc(sizeof(float) * filter_len); - f = (double*) mxGetPr(FREQ_FILTER); - for (i=0;i 5) { + uint32_t filter_len = 0; + float *filter; + double *f; + + filter_len = mxGetNumberOfElements(FREQ_FILTER); + filter = malloc(sizeof(float) * filter_len); + f = (double*) mxGetPr(FREQ_FILTER); + for (i=0;i> (nof_bits-i-1)) & 0x1; + } + *bits += nof_bits; +} + void srslte_bit_pack(uint32_t value, uint8_t **bits, int nof_bits) { int i; @@ -77,6 +87,18 @@ uint32_t srslte_bit_unpack(uint8_t **bits, int nof_bits) return value; } +uint64_t srslte_bit_unpack_l(uint8_t **bits, int nof_bits) +{ + int i; + uint64_t value=0; + + for(i=0; i=M-1) { + last[i] = (2+i-M/2)*input[N-1]-(1+i-M/2)*input[N-2]; + } else { + last[i] = input[N-M+i+1]; + } + } + + for (i=0;i