MAC test working until ConnectionSetupComplete

master
ismagom 10 years ago
parent 8f40bb2f73
commit 4a909ef56c

@ -1,15 +1,15 @@
ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',8,'RNTI',81,'CyclicPrefixUL','Normal','NTxAnts',1); ueConfig=struct('NCellID',1,'NULRB',25,'NSubframe',0,'RNTI',65,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',(1:4)','Modulation','QPSK','RV',0,'Shortened',0); puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',24,'Modulation','QPSK','RV',0,'Shortened',0);
subframe_rx=lteSCFDMADemodulate(ueConfig,x.*transpose(exp(-1i*2*pi*0.26*(1:length(x))/128))); TBS=72;
cfo=1146;
subframe_rx=lteSCFDMADemodulate(ueConfig,x.*exp(-1i*2*pi*cfo/15000*transpose(1:length(x))/512));
idx=ltePUSCHIndices(ueConfig,puschConfig); idx=ltePUSCHIndices(ueConfig,puschConfig);
pusch_rx=subframe_rx(idx); pusch_rx=subframe_rx(idx);
[hest, noiseest] = lteULChannelEstimate(ueConfig,puschConfig,subframe_rx); [hest, noiseest] = lteULChannelEstimate(ueConfig,puschConfig,subframe_rx);
ce=hest(idx); ce=hest(idx);
[cws,symbols] = ltePUSCHDecode(ueConfig,puschConfig,pusch_rx,ce,noiseest); [cws,symbols] = ltePUSCHDecode(ueConfig,puschConfig,pusch_rx,ce,noiseest);
[trblkout,blkcrc,stateout] = lteULSCHDecode(ueConfig,puschConfig,88,cws); [trblkout,blkcrc,stateout] = lteULSCHDecode(ueConfig,puschConfig,TBS,cws);
disp(blkcrc) disp(blkcrc)
subplot(1,2,1)
scatter(real(symbols),imag(symbols)) scatter(real(symbols),imag(symbols))
subplot(1,2,2)
plot(angle(hest))

@ -1,14 +1,16 @@
clear ueConfig=struct('NCellID',1,'NULRB',25,'NSubframe',8,'RNTI',77,'CyclicPrefixUL','Normal','NTxAnts',1);
ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',1,'RNTI',18,'CyclicPrefixUL','Normal','NTxAnts',1); puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',24,'Modulation','QAM16','RV',0,'Shortened',0);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[1:4]','Modulation','QPSK','RV',0,'Shortened',0);
addpath('../../debug/srslte/lib/phch/test') addpath('../../debug/srslte/lib/phch/test')
TBs=0:13:211; TBs=336;
cqilen=[0, 8, 17]; cqilen=0;
mods={'QPSK','16QAM','64QAM'};
rvs=0; rvs=0;
betas=[2.0 2.5 6.25]; mods={'16QAM'};
betas=0;
subf=8;
trblkin=[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0];
for i=1:length(TBs) for i=1:length(TBs)
for m=1:length(mods) for m=1:length(mods)
@ -17,9 +19,10 @@ for i=1:length(TBs)
for bri=1:length(betas) for bri=1:length(betas)
for back=1:length(betas) for back=1:length(betas)
for c=1:length(cqilen) for c=1:length(cqilen)
for s=1:length(subf)
trblkin=randi(2,TBs(i),1)-1; fprintf('Subf=%d, RV=%d\n', subf(s), rvs(r));
%trblkin=randi(2,TBs(i),1)-1;
ueConfig.NSubframe=subf(s);
puschConfig.Modulation = mods{m}; puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r); puschConfig.RV = rvs(r);
puschConfig.BetaCQI = betas(bcqi); puschConfig.BetaCQI = betas(bcqi);
@ -38,18 +41,24 @@ for i=1:length(TBs)
end end
if (cqilen(c)>0 || TBs(i)>0) if (cqilen(c)>0 || TBs(i)>0)
[cw, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit,[]); [cw, info]=lteULSCH(ueConfig,puschConfig,trblkin);
cw_mat=ltePUSCH(ueConfig,puschConfig,cw); cw_mat=ltePUSCH(ueConfig,puschConfig,cw);
drs=ltePUSCHDRS(ueConfig,puschConfig);
idx=ltePUSCHIndices(ueConfig,puschConfig); idx=ltePUSCHIndices(ueConfig,puschConfig);
drs_ind = ltePUSCHDRSIndices(ueConfig,puschConfig);
subframe_mat = lteULResourceGrid(ueConfig); subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=cw_mat; subframe_mat(idx)=cw_mat;
subframe_mat(drs_ind)=drs;
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0); waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
plot(abs(x-waveform*sqrt(512)))
[waveform_lib, subframe_lib, cwlib]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
err=mean(abs(waveform-waveform_lib)); % [waveform_lib, subframe_lib, cwlib]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
if (err > 10^-6) % err=mean(abs(waveform-waveform_lib));
disp(err) % if (err > 10^-6)
error('Error!'); % disp(err)
% error('Error!');
% end
end end
end end
end end
@ -60,10 +69,3 @@ for i=1:length(TBs)
end end
end end
if (length(TBs) == 1)
%disp(info)
%n=1:length(mat);
%plot(abs(double(mat)-double(lib)))
%plot(n,real(lib(n)),n,real(mat(n)))
plot(abs(waveform_lib-waveform))
end

@ -26,7 +26,7 @@ INSTALL(DIRECTORY include/
) )
FILE(GLOB SOURCES "src/*.cc") FILE(GLOB SOURCES "src/*.cc")
ADD_LIBRARY(srsapps_common SHARED ${SOURCES}) ADD_LIBRARY(srsapps_common SHARED ${SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src/threads.c)
INSTALL(TARGETS srsapps_common DESTINATION ${LIBRARY_DIR}) INSTALL(TARGETS srsapps_common DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srsapps_common) SRSLTE_SET_PIC(srsapps_common)

@ -0,0 +1,40 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
bool threads_new_rt(pthread_t *thread, void *(*start_routine) (void*), void *arg);
bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu);
void threads_print_self();
#ifdef __cplusplus
}
#endif

@ -0,0 +1,116 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include "srsapps/common/threads.h"
bool threads_new_rt(pthread_t *thread, void *(*start_routine) (void*), void *arg) {
return threads_new_rt_cpu(thread, start_routine, arg, -1);
}
bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu) {
bool ret = false;
pthread_attr_t attr;
struct sched_param param;
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_init(&attr);
if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {
perror("pthread_attr_setinheritsched");
}
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
perror("pthread_attr_setschedpolicy");
}
if (pthread_attr_setschedparam(&attr, &param)) {
perror("pthread_attr_setschedparam");
fprintf(stderr, "Error not enough privileges to set Scheduling priority\n");
}
if (cpu != -1) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET((size_t) cpu, &cpuset);
if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset)) {
perror("pthread_attr_setaffinity_np");
}
}
if (pthread_create(thread, &attr, start_routine, arg)) {
perror("pthread_create");
} else {
ret = true;
}
pthread_attr_destroy(&attr);
return ret;
}
void threads_print_self() {
pthread_t thread;
cpu_set_t cpuset;
struct sched_param param;
int policy;
const char *p;
int s,j;
thread = pthread_self();
s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0) {
printf("error pthread_getaffinity_np: %s\n",strerror(s));
}
printf("Set returned by pthread_getaffinity_np() contained:\n");
for (j = 0; j < CPU_SETSIZE; j++) {
if (CPU_ISSET(j, &cpuset)) {
printf(" CPU %d\n", j);
}
}
s = pthread_getschedparam(thread, &policy, &param);
if (s != 0) {
printf("error pthread_getaffinity_np: %s\n", strerror(s));
}
switch(policy) {
case SCHED_FIFO:
p = "SCHED_FIFO";
break;
case SCHED_RR:
p = "SCHED_RR";
break;
default:
p = "Other";
break;
}
printf("Sched policy is %s. Priority is %d\n",p,param.sched_priority);
}

@ -140,6 +140,7 @@ private:
/* Functions for MAC Timers */ /* Functions for MAC Timers */
timers timers_db; timers timers_db;
uint16_t phy_rnti;
void setup_timers(); void setup_timers();
void timeAlignmentTimerExpire(); void timeAlignmentTimerExpire();

@ -77,7 +77,7 @@ namespace ue {
const static int NOF_UL_LCH = MAC_LCH_DTCH2_UL - MAC_LCH_CCCH_UL; const static int NOF_UL_LCH = MAC_LCH_DTCH2_UL - MAC_LCH_CCCH_UL;
const static int DEFAULT_MSG_SZ = 8*1024; // 8 Kbytes const static int DEFAULT_MSG_SZ = 8*1024; // 8 Kbytes
const static int DEFAULT_NOF_MESSAGES = 8; const static int DEFAULT_NOF_MESSAGES = 64;
qbuff* get(mac_lch_t ch) { qbuff* get(mac_lch_t ch) {

@ -69,7 +69,8 @@ public:
private: private:
bool assemble_pdu(uint32_t pdu_sz); bool assemble_pdu(uint32_t pdu_sz);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu); bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, uint32_t *sdu_sz); bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, bool *is_first);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, uint32_t *sdu_sz, bool *is_first);
int64_t Bj[mac_io::NOF_UL_LCH]; int64_t Bj[mac_io::NOF_UL_LCH];
int PBR[mac_io::NOF_UL_LCH]; // -1 sets to infinity int PBR[mac_io::NOF_UL_LCH]; // -1 sets to infinity

@ -86,6 +86,10 @@ public:
} }
} }
uint32_t nof_subh() {
return nof_subheaders;
}
bool new_subh() { bool new_subh() {
if (nof_subheaders < max_subheaders - 1) { if (nof_subheaders < max_subheaders - 1) {
nof_subheaders++; nof_subheaders++;
@ -104,6 +108,13 @@ public:
} }
} }
void del_subh() {
if (cur_idx > 0 && nof_subheaders > 0) {
cur_idx--;
nof_subheaders--;
}
}
SubH* get() { SubH* get() {
if (cur_idx >= 0) { if (cur_idx >= 0) {
return &subheaders[cur_idx]; return &subheaders[cur_idx];
@ -196,8 +207,9 @@ public:
void write_subheader(uint8_t** ptr, bool is_last); void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t **ptr); void write_payload(uint8_t **ptr);
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes); bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes);
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes, bool is_first);
bool set_c_rnti(uint16_t crnti); bool set_c_rnti(uint16_t crnti);
bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format); bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool update_size);
bool set_con_res_id(uint64_t con_res_id); bool set_con_res_id(uint64_t con_res_id);
bool set_ta_cmd(uint8_t ta_cmd); bool set_ta_cmd(uint8_t ta_cmd);
bool set_phd(uint8_t phd); bool set_phd(uint8_t phd);
@ -228,11 +240,13 @@ public:
bool write_packet(uint8_t *ptr); bool write_packet(uint8_t *ptr);
bool has_space_ce(uint32_t nbytes); bool has_space_ce(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes); bool has_space_sdu(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes, bool is_first);
uint32_t size(); uint32_t size();
uint32_t rem_size(); uint32_t rem_size();
static uint32_t size_plus_header_sdu(uint32_t nbytes); static uint32_t size_plus_header_sdu(uint32_t nbytes);
bool update_space_ce(uint32_t nbytes); bool update_space_ce(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes); bool update_space_sdu(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes, bool is_first);
void fprint(FILE *stream); void fprint(FILE *stream);
}; };

@ -65,12 +65,14 @@ public:
uint32_t buff_size[4]; uint32_t buff_size[4];
} bsr_t; } bsr_t;
bool need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t nof_padding_bytes, bsr_t *bsr); uint32_t need_to_send_bsr_on_ul_grant(uint32_t grant_size);
bool generate_bsr_on_ul_grant(uint32_t nof_padding_bytes, bsr_t *bsr);
bool need_to_send_sr(); bool need_to_send_sr();
bool need_to_reset_sr();
private: private:
bool is_pending_sr; bool reset_sr;
mac_params *params_db; mac_params *params_db;
mac_io *mac_io_h; mac_io *mac_io_h;
timers *timers_db; timers *timers_db;
@ -78,19 +80,21 @@ private:
bool initiated; bool initiated;
const static int MAX_LCID = 20; const static int MAX_LCID = 20;
int lcg[MAX_LCID]; int lcg[MAX_LCID];
uint32_t last_pending_data[MAX_LCID];
int priorities[MAX_LCID]; int priorities[MAX_LCID];
uint32_t find_max_priority_lcid(); uint32_t find_max_priority_lcid();
enum {NONE, REGULAR, PADDING, PERIODIC} triggered_bsr_type; typedef enum {NONE, REGULAR, PADDING, PERIODIC} triggered_bsr_type_t;
triggered_bsr_type_t triggered_bsr_type;
bool timer_periodic; bool timer_periodic;
bool timer_retx; bool timer_retx;
bsr_t pending_bsr;
bool sr_is_sent; bool sr_is_sent;
bool check_all_channels(); void update_pending_data();
bool check_highest_channel(); bool check_highest_channel();
bool check_single_channel(); bool check_single_channel();
void get_pending_bsr_format(uint32_t nof_padding_bytes); bool generate_bsr(bsr_t *bsr, uint32_t nof_padding_bytes);
char* bsr_type_tostring(triggered_bsr_type_t type);
char* bsr_format_tostring(bsr_format_t format);
}; };
} }
} }

@ -58,6 +58,7 @@ private:
phy *phy_h; phy *phy_h;
log *log_h; log *log_h;
bool initiated; bool initiated;
bool do_ra;
}; };
} }
} }

@ -92,19 +92,19 @@ void demux::push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits)
// Unpack DLSCH MAC PDU // Unpack DLSCH MAC PDU
pending_mac_msg.init(nof_bits/8); pending_mac_msg.init(nof_bits/8);
pending_mac_msg.parse_packet(mac_pdu); pending_mac_msg.parse_packet(mac_pdu);
pending_mac_msg.fprint(stdout); //pending_mac_msg.fprint(stdout);
// Look for Contention Resolution UE ID // Look for Contention Resolution UE ID
while(pending_mac_msg.next()) { while(pending_mac_msg.next()) {
if (pending_mac_msg.get()->ce_type() == sch_subh::CON_RES_ID) { if (pending_mac_msg.get()->ce_type() == sch_subh::CON_RES_ID) {
contention_resolution_id = pending_mac_msg.get()->get_con_res_id(); contention_resolution_id = pending_mac_msg.get()->get_con_res_id();
has_pending_contention_resolution_id = true; has_pending_contention_resolution_id = true;
Info("Found Contention Resolution ID CE\n"); Debug("Found Contention Resolution ID CE\n");
} }
} }
pending_mac_msg.reset(); pending_mac_msg.reset();
pending_temp_rnti = true; pending_temp_rnti = true;
Info("Saved MAC PDU with Temporal C-RNTI in buffer\n"); Debug("Saved MAC PDU with Temporal C-RNTI in buffer\n");
} else { } else {
Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n"); Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n");
} }
@ -148,7 +148,7 @@ void demux::process_pdu(sch_pdu *pdu_msg)
qbuff *dest_lch = mac_io_h->get(pdu_msg->get()->get_sdu_lcid()); qbuff *dest_lch = mac_io_h->get(pdu_msg->get()->get_sdu_lcid());
if (dest_lch) { if (dest_lch) {
dest_lch->send(pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes()*8); dest_lch->send(pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes()*8);
Debug("Sent MAC SDU len=%d bytes to lchid=%d\n", Info("Sent MAC SDU len=%d bytes to lchid=%d\n",
pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid()); pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid());
} else { } else {
Error("Getting destination channel LCID=%d\n", pdu_msg->get()->get_sdu_lcid()); Error("Getting destination channel LCID=%d\n", pdu_msg->get()->get_sdu_lcid());

@ -178,7 +178,7 @@ void dl_harq_entity::dl_harq_process::receive_data(uint32_t tti, srslte::ue::dl_
} }
} }
Info("DL PID %d: TBS=%d, RV=%d, MCS=%d, crc=%s\n", pid, cur_grant.get_tbs(), cur_grant.get_rv(), cur_grant.get_mcs(), ack?"OK":"NOK"); Info("DL PID %d: TBS=%d, RV=%d, MCS=%d, crc=%s, PHY TTI: %d\n", pid, cur_grant.get_tbs(), cur_grant.get_rv(), cur_grant.get_mcs(), ack?"OK":"NOK", phy_h->get_current_tti());
} }
// Implement 5.3.2.2 // Implement 5.3.2.2

@ -30,6 +30,7 @@
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include "srsapps/common/threads.h"
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac.h" #include "srsapps/ue/mac/mac.h"
@ -47,6 +48,7 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
tti = 0; tti = 0;
is_synchronized = false; is_synchronized = false;
last_temporal_crnti = 0; last_temporal_crnti = 0;
phy_rnti = 0;
bsr_procedure.init(log_h, &timers_db, &params_db, &mac_io_lch); bsr_procedure.init(log_h, &timers_db, &params_db, &mac_io_lch);
mux_unit.init(log_h, &mac_io_lch, &bsr_procedure); mux_unit.init(log_h, &mac_io_lch, &bsr_procedure);
@ -55,18 +57,10 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
sr_procedure.init(log_h, &params_db, phy_h); sr_procedure.init(log_h, &params_db, phy_h);
reset(); reset();
pthread_attr_t attr; if (threads_new_rt(&mac_thread, mac_thread_fnc, this)) {
struct sched_param param;
param.sched_priority = sched_get_priority_min(SCHED_FIFO) ;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
if (!pthread_create(&mac_thread, &attr, mac_thread_fnc, this)) {
started = true; started = true;
} else {
perror("pthread_create");
} }
return started; return started;
} }
@ -179,14 +173,18 @@ void mac::main_radio_loop() {
// Check if BSR procedure need to start SR // Check if BSR procedure need to start SR
if (bsr_procedure.need_to_send_sr()) { if (bsr_procedure.need_to_send_sr()) {
Info("Starting SR procedure by BSR request\n"); Info("Starting SR procedure by BSR request, PHY TTI=%d\n", phy_h->get_current_tti());
sr_procedure.start(); sr_procedure.start();
} else if (bsr_procedure.need_to_reset_sr()) {
Info("Resetting SR procedure by BSR request\n");
sr_procedure.reset();
} }
sr_procedure.step(tti); sr_procedure.step(tti);
// Check SR if we need to start RA // Check SR if we need to start RA
if (sr_procedure.need_random_access()) { if (sr_procedure.need_random_access()) {
ra_procedure.start_mac_order(); Info("Starting RA procedure by MAC order\n");
//ra_procedure.start_mac_order();
} }
ra_procedure.step(tti); ra_procedure.step(tti);
@ -198,22 +196,20 @@ void mac::main_radio_loop() {
// Process DL grants always // Process DL grants always
process_dl_grants(tti); process_dl_grants(tti);
// Process UL grants if RA procedure is done and we have pending data or in contention resolution
if (ra_procedure.is_contention_resolution() ||
ra_procedure.is_successful() && mux_unit.is_pending_ccch_sdu())
{
process_ul_grants(tti);
}
// Send pending HARQ ACK, if any, and contention resolution is resolved // Send pending HARQ ACK, if any, and contention resolution is resolved
if (dl_harq.is_ack_pending_resolution()) { if (dl_harq.is_ack_pending_resolution()) {
ra_procedure.step(tti); ra_procedure.step(tti);
if (ra_procedure.is_successful() || ra_procedure.is_response_error()) { if (ra_procedure.is_successful() || ra_procedure.is_response_error()) {
Info("Sending pending ACK for contention resolution\n"); Info("Sending pending ACK for contention resolution PHY TTI: %d\n", phy_h->get_current_tti());
dl_harq.send_pending_ack_contention_resolution(); dl_harq.send_pending_ack_contention_resolution();
} }
} }
// Process UL grants if RA procedure is done and we have pending data or in contention resolution
if (ra_procedure.is_contention_resolution() || ra_procedure.is_successful()) {
process_ul_grants(tti);
}
timers_db.step_all(); timers_db.step_all();
// Check if there is pending CCCH SDU in Multiplexing Unit // Check if there is pending CCCH SDU in Multiplexing Unit
@ -224,6 +220,16 @@ void mac::main_radio_loop() {
ra_procedure.start_rlc_order(); ra_procedure.start_rlc_order();
} }
} }
if (ra_procedure.is_successful() && phy_rnti != params_db.get_param(mac_params::RNTI_C) && params_db.get_param(mac_params::RNTI_C) > 0) {
phy_rnti = params_db.get_param(mac_params::RNTI_C);
Info("Setting PHY RNTI=%d\n", phy_rnti);
// This operation takes a while, do nothing for the rest 100 slots to re-align with PHY
phy_h->set_crnti(phy_rnti);
for (int i=0;i<100;i++) {
tti = ttisync->wait();
}
}
} }
} }
} }
@ -475,7 +481,7 @@ int mac::recv_dtch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
int mac::recv_dcch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes) int mac::recv_dcch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
{ {
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes); return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
} }

@ -211,7 +211,8 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
pdu_msg.init(pdu_sz_nbits/8, true); pdu_msg.init(pdu_sz_nbits/8, true);
// MAC control element for C-RNTI or data from UL-CCCH // MAC control element for C-RNTI or data from UL-CCCH
if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg)) { bool is_first = true;
if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg, &is_first)) {
if (pending_crnti_ce) { if (pending_crnti_ce) {
if (pdu_msg.new_subh()) { if (pdu_msg.new_subh()) {
pdu_msg.next(); pdu_msg.next();
@ -223,15 +224,19 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
} }
pending_crnti_ce = 0; pending_crnti_ce = 0;
uint32_t bsr_payload_sz = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_msg.rem_size());
bsr_proc::bsr_t bsr; 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; // MAC control element for BSR, with exception of BSR included for padding;
if (send_bsr_normal) { sch_subh *bsr_subh = NULL;
if (bsr_payload_sz) {
Info("Including BSR CE size %d\n", bsr_payload_sz);
if (pdu_msg.new_subh()) {
pdu_msg.next(); pdu_msg.next();
pdu_msg.get()->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format)); bsr_subh = pdu_msg.get();
pdu_msg.update_space_ce(bsr_payload_sz);
}
} }
// MAC control element for PHR // MAC control element for PHR
// TODO // TODO
@ -240,7 +245,7 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
for (int i=0;i<mac_io::NOF_UL_LCH;i++) { for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
bool res = true; bool res = true;
while ((Bj[i] > 0 || PBR[i] < 0) && res) { while ((Bj[i] > 0 || PBR[i] < 0) && res) {
res = allocate_sdu(lchid_sorted[i], &pdu_msg, &sdu_sz); res = allocate_sdu(lchid_sorted[i], &pdu_msg, &sdu_sz, &is_first);
if (res && PBR[i] >= 0) { if (res && PBR[i] >= 0) {
Bj[i] -= sdu_sz; Bj[i] -= sdu_sz;
} }
@ -252,11 +257,18 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
while (allocate_sdu(lchid_sorted[i], &pdu_msg)); while (allocate_sdu(lchid_sorted[i], &pdu_msg));
} }
// MAC control element for BSR included for padding. bool send_bsr = bsr_procedure->generate_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
bool send_bsr_padding = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_sz_nbits/8, pdu_msg.rem_size(), &bsr); // Insert Padding BSR if not inserted Regular/Periodic BSR
if (send_bsr_padding) { if (!bsr_payload_sz && send_bsr) {
if (pdu_msg.new_subh()) {
pdu_msg.next(); pdu_msg.next();
pdu_msg.get()->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format)); bsr_subh = pdu_msg.get();
}
}
// And set the BSR
if (bsr_subh) {
bsr_subh->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format), bsr_payload_sz?false:true);
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
@ -269,7 +281,9 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
} }
} }
Info("Assembled MAC PDU msg size %d bytes\n", pdu_msg.size()); Info("Assembled MAC PDU msg size %d/%d bytes\n", pdu_msg.size(), pdu_sz_nbits/8);
pdu_msg.fprint(stdout);
/* Generate MAC PDU and save to buffer */ /* Generate MAC PDU and save to buffer */
if (pdu_msg.write_packet(buff)) { if (pdu_msg.write_packet(buff)) {
pdu_buff.push(pdu_sz_nbits); pdu_buff.push(pdu_sz_nbits);
@ -282,25 +296,34 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg) bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg)
{ {
return allocate_sdu(lcid, pdu_msg, NULL); return allocate_sdu(lcid, pdu_msg, NULL, NULL);
}
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, bool *is_first)
{
return allocate_sdu(lcid, pdu_msg, NULL, is_first);
} }
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz) bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz, bool *is_first)
{ {
// Get n-th pending SDU pointer and length // Get n-th pending SDU pointer and length
uint32_t buff_len; uint32_t buff_len;
uint8_t *buff_ptr = (uint8_t*) mac_io_h->get(mac_io::MAC_LCH_CCCH_UL + lcid)->pop(&buff_len, nof_tx_pkts[lcid]); 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 (buff_ptr && buff_len > 0) { // there is pending SDU to allocate
if (sdu_sz) { if (sdu_sz) {
*sdu_sz = buff_len; *sdu_sz = buff_len;
} }
if (pdu_msg->new_subh()) { // there is space for a new subheader if (pdu_msg->new_subh()) { // there is space for a new subheader
pdu_msg->next(); pdu_msg->next();
if (pdu_msg->get()->set_sdu(lcid, buff_ptr, buff_len/8)) { // new SDU could be added if (pdu_msg->get()->set_sdu(lcid, buff_ptr, buff_len/8, is_first?*is_first:false)) { // new SDU could be added
if (is_first) {
*is_first = false;
}
// Increase number of pop'ed packets from queue // Increase number of pop'ed packets from queue
nof_tx_pkts[lcid]++; nof_tx_pkts[lcid]++;
return true; return true;
} else {
pdu_msg->del_subh();
} }
} }
} }
@ -330,6 +353,7 @@ uint8_t* mux::msg3_pop(uint32_t TB_size)
{ {
uint32_t len; uint32_t len;
uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len); uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len);
if (msg3) {
if (len < TB_size) { if (len < TB_size) {
// Pad with zeros without exceeding maximum buffer size // Pad with zeros without exceeding maximum buffer size
if (TB_size <= MSG3_BUFF_SZ) { if (TB_size <= MSG3_BUFF_SZ) {
@ -339,6 +363,7 @@ uint8_t* mux::msg3_pop(uint32_t TB_size)
return NULL; return NULL;
} }
} }
}
return msg3; return msg3;
} }

@ -47,21 +47,43 @@ void sch_subh::fprint(FILE* stream)
if (is_sdu()) { if (is_sdu()) {
fprintf(stream, "SDU LCHID=%d, SDU nof_bytes=%d\n", lcid, nof_bytes); fprintf(stream, "SDU LCHID=%d, SDU nof_bytes=%d\n", lcid, nof_bytes);
} else { } else {
if (parent->is_ul()) {
switch(lcid) { switch(lcid) {
case C_RNTI: case C_RNTI:
fprintf(stream, "C-RNTI CE: %d\n", get_c_rnti()); fprintf(stream, "C-RNTI CE: %d\n", get_c_rnti());
break; break;
case PHD_REPORT:
fprintf(stream, "C-RNTI CE: %d\n", get_c_rnti());
break;
case TRUNC_BSR:
fprintf(stream, "Truncated BSR CE\n");
break;
case SHORT_BSR:
fprintf(stream, "Short BSR CE\n");
break;
case LONG_BSR:
fprintf(stream, "Long BSR CE\n");
break;
case PADDING:
fprintf(stream, "PADDING\n");
}
} else {
switch(lcid) {
case CON_RES_ID: case CON_RES_ID:
fprintf(stream, "Contention Resolution ID CE: 0x%lx\n", get_con_res_id()); fprintf(stream, "Contention Resolution ID CE: 0x%lx\n", get_con_res_id());
break; break;
case TA_CMD: case TA_CMD:
fprintf(stream, "Time Advance Command CE: %d\n", get_ta_cmd()); fprintf(stream, "Time Advance Command CE: %d\n", get_ta_cmd());
break; break;
case DRX_CMD:
fprintf(stream, "DRX Command CE: Not implemented\n");
break;
case PADDING: case PADDING:
fprintf(stream, "PADDING\n"); fprintf(stream, "PADDING\n");
} }
} }
} }
}
void sch_pdu::parse_packet(uint8_t *ptr) void sch_pdu::parse_packet(uint8_t *ptr)
{ {
@ -86,9 +108,26 @@ bool sch_pdu::write_packet(uint8_t* ptr)
{ {
uint8_t *init_ptr = ptr; uint8_t *init_ptr = ptr;
bool last_is_padding = false; bool last_is_padding = false;
// Add multi-byte padding if necessary
if (rem_len > 2) { // Find last SDU or CE
int last_sh;
int last_sdu = nof_subheaders-1;
while(!subheaders[last_sdu].is_sdu() && last_sdu >= 0) {
last_sdu--;
}
int last_ce = nof_subheaders-1;
while(subheaders[last_ce].is_sdu() && last_ce >= 0) {
last_ce--;
}
last_sh = subheaders[last_sdu].is_sdu()?last_sdu:last_ce;
// Add multi-byte padding if there are more than 2 bytes or there are 2 bytes
// and there is at least one SDU
if (rem_len > 2 || (rem_len==2 && subheaders[last_sdu].is_sdu())) {
last_is_padding = true; last_is_padding = true;
} else if (rem_len > 0) {
if (subheaders[last_sdu].is_sdu()) {
rem_len++;
} }
// Add single or two-byte padding if required // Add single or two-byte padding if required
if (rem_len == 1 || rem_len == 2) { if (rem_len == 1 || rem_len == 2) {
@ -99,19 +138,8 @@ bool sch_pdu::write_packet(uint8_t* ptr)
} }
rem_len = 0; rem_len = 0;
} }
int last_sh;
if (!last_is_padding) {
// Find last SDU or CE
int last_sdu = nof_subheaders-1;
while(!subheaders[last_sdu].is_sdu() && last_sdu >= 0) {
last_sdu--;
}
int last_ce = nof_subheaders-1;
while(subheaders[last_ce].is_sdu() && last_ce >= 0) {
last_ce--;
} }
last_sh = subheaders[last_sdu].is_sdu()?last_sdu:last_ce; if (last_is_padding) {
} else {
last_sh = -1; last_sh = -1;
} }
// Write subheaders for MAC CE first // Write subheaders for MAC CE first
@ -172,9 +200,16 @@ bool sch_pdu::has_space_ce(uint32_t nbytes)
return false; return false;
} }
} }
bool sch_pdu::has_space_sdu(uint32_t nbytes) bool sch_pdu::has_space_sdu(uint32_t nbytes)
{ {
if (rem_len >= size_plus_header_sdu(nbytes)) { return has_space_sdu(nbytes, false);
}
bool sch_pdu::has_space_sdu(uint32_t nbytes, bool is_first)
{
uint32_t sizeh_first=is_first?1:0;
if (rem_len >= size_plus_header_sdu(nbytes)-sizeh_first) {
return true; return true;
} else { } else {
return false; return false;
@ -186,10 +221,15 @@ bool sch_pdu::update_space_ce(uint32_t nbytes)
rem_len -= nbytes + 1; rem_len -= nbytes + 1;
} }
} }
bool sch_pdu::update_space_sdu(uint32_t nbytes) bool sch_pdu::update_space_sdu(uint32_t nbytes) {
return update_space_sdu(nbytes, false);
}
bool sch_pdu::update_space_sdu(uint32_t nbytes, bool is_first)
{ {
if (has_space_sdu(nbytes)) { uint32_t sizeh_first=is_first?1:0;
rem_len -= size_plus_header_sdu(nbytes); if (has_space_sdu(nbytes, is_first)) {
rem_len -= (size_plus_header_sdu(nbytes)-sizeh_first);
} }
} }
@ -305,7 +345,7 @@ void sch_subh::set_padding()
} }
bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format) bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format, bool update_size)
{ {
uint32_t nonzero_lcg=0; uint32_t nonzero_lcg=0;
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
@ -314,18 +354,22 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format)
} }
} }
uint32_t ce_size = format==LONG_BSR?3:1; uint32_t ce_size = format==LONG_BSR?3:1;
if (((sch_pdu*)parent)->has_space_ce(ce_size)) { if (((sch_pdu*)parent)->has_space_ce(ce_size) || !update_size) {
uint8_t *ptr = ce_payload; uint8_t *ptr = ce_payload;
if (format==LONG_BSR) { if (format==LONG_BSR) {
bzero(ce_payload, 3*8*sizeof(uint8_t));
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6); srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6);
} }
} else { } else {
bzero(ce_payload, 8*sizeof(uint8_t));
srslte_bit_pack(nonzero_lcg, &ptr, 2); srslte_bit_pack(nonzero_lcg, &ptr, 2);
srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6); srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6);
} }
lcid = format; lcid = format;
if (update_size) {
((sch_pdu*)parent)->update_space_ce(ce_size); ((sch_pdu*)parent)->update_space_ce(ce_size);
}
return true; return true;
} else { } else {
return false; return false;
@ -371,13 +415,19 @@ bool sch_subh::set_phd(uint8_t phd)
return false; return false;
} }
} }
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_) bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_)
{ {
if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_)) { return set_sdu(lcid_, ptr, nof_bytes_, false);
}
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_, bool is_first)
{
if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_, is_first)) {
sdu_payload_ptr = ptr; sdu_payload_ptr = ptr;
nof_bytes = nof_bytes_; nof_bytes = nof_bytes_;
lcid = lcid_; lcid = lcid_;
((sch_pdu*)parent)->update_space_sdu(nof_bytes_); ((sch_pdu*)parent)->update_space_sdu(nof_bytes_, is_first);
return true; return true;
} else { } else {
return false; return false;
@ -423,6 +473,7 @@ void sch_subh::write_payload(uint8_t** ptr)
if (is_sdu()) { if (is_sdu()) {
src = sdu_payload_ptr; src = sdu_payload_ptr;
} else { } else {
nof_bytes = sizeof_ce(lcid, parent->is_ul());
src = ce_payload; src = ce_payload;
} }
memcpy(*ptr, src, nof_bytes*8*sizeof(uint8_t)); memcpy(*ptr, src, nof_bytes*8*sizeof(uint8_t));
@ -618,7 +669,7 @@ uint8_t sch_subh::buff_size_table(uint32_t buffer_size) {
return 63; return 63;
} else { } else {
for (int i=0;i<61;i++) { for (int i=0;i<61;i++) {
if (buffer_size > btable[i]) { if (buffer_size < btable[i]) {
return 1+i; return 1+i;
} }
} }

@ -38,9 +38,11 @@ bsr_proc::bsr_proc()
initiated = false; initiated = false;
timer_periodic = false; timer_periodic = false;
timer_retx = false; timer_retx = false;
reset_sr = false;
for (int i=0;i<MAX_LCID;i++) { for (int i=0;i<MAX_LCID;i++) {
lcg[i] = -1; lcg[i] = -1;
priorities[i] = -1; priorities[i] = -1;
last_pending_data[i] = 0;
} }
triggered_bsr_type=NONE; triggered_bsr_type=NONE;
} }
@ -65,54 +67,51 @@ void bsr_proc::timer_expired(uint32_t timer_id) {
case mac::BSR_TIMER_PERIODIC: case mac::BSR_TIMER_PERIODIC:
if (triggered_bsr_type == NONE) { if (triggered_bsr_type == NONE) {
// Check condition 4 in Sec 5.4.5 // Check condition 4 in Sec 5.4.5
if (check_all_channels()) { //triggered_bsr_type = PERIODIC;
triggered_bsr_type = PERIODIC; Info("BSR PERIODIC disabled\n");
Info("BSR set to PERIODIC\n");
}
} }
break; break;
case mac::BSR_TIMER_RETX: case mac::BSR_TIMER_RETX:
// Check condition 3 in Sec 5.4.5 // Enable reTx of SR
if (check_all_channels()) { //triggered_bsr_type = REGULAR;
Info("BSR set to REGULAR RETX\n"); Info("BSR reTX disabled\n");
triggered_bsr_type = REGULAR; sr_is_sent = false;
sr_is_sent = false; // Enable reTx of SR
}
break; break;
} }
} }
// Checks if data is available for a a channel with higher priority than others // Checks if data is available for a a channel with higher priority than others
bool bsr_proc::check_highest_channel() { bool bsr_proc::check_highest_channel() {
uint32_t pending_data = 0; int pending_data_lcid = -1;
uint32_t pending_data_lcid = 0;
for (int i=0;i<mac_io::NOF_UL_LCH && !pending_data;i++) { for (int i=0;i<mac_io::NOF_UL_LCH && pending_data_lcid == -1;i++) {
if (lcg[i] >= 0) { if (lcg[i] >= 0) {
pending_data = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8; if (!mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
if (pending_data > 0) {
pending_data_lcid = i; pending_data_lcid = i;
for (int j=0;j<mac_io::NOF_UL_LCH;j++) { for (int j=0;j<mac_io::NOF_UL_LCH;j++) {
if (!mac_io_h->get(j+mac_io::MAC_LCH_CCCH_UL)->isempty()) { if (!mac_io_h->get(j+mac_io::MAC_LCH_CCCH_UL)->isempty()) {
if (priorities[j] > priorities[i]) { if (priorities[j] > priorities[i]) {
pending_data = 0; pending_data_lcid = -1;
} }
} }
} }
} }
} }
} }
if (pending_data) { if (pending_data_lcid >= 0) {
pending_bsr.buff_size[lcg[pending_data_lcid]] = pending_data; // If there is new data available for this logical channel
uint32_t nbytes = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
if (nbytes > last_pending_data[pending_data_lcid])
{
if (triggered_bsr_type != REGULAR) { if (triggered_bsr_type != REGULAR) {
Info("Triggered REGULAR BSR for Max Priority LCID=%d\n", pending_data_lcid); Info("Triggered REGULAR BSR for Max Priority LCID=%d\n", pending_data_lcid);
} }
triggered_bsr_type = REGULAR; triggered_bsr_type = REGULAR;
return true; return true;
} else {
return false;
} }
} }
return false;
}
// Checks if only one logical channel has data avaiable for Tx // Checks if only one logical channel has data avaiable for Tx
bool bsr_proc::check_single_channel() { bool bsr_proc::check_single_channel() {
@ -128,61 +127,62 @@ bool bsr_proc::check_single_channel() {
} }
} }
if (nof_nonzero_lcid == 1) { if (nof_nonzero_lcid == 1) {
pending_bsr.buff_size[lcg[pending_data_lcid]] = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8; uint32_t nbytes = mac_io_h->get(pending_data_lcid+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
// If there is new data available for this logical channel
if (nbytes > last_pending_data[pending_data_lcid]) {
triggered_bsr_type = REGULAR; triggered_bsr_type = REGULAR;
Info("Triggered REGULAR BSR for single LCID=%d\n", pending_data_lcid); Info("Triggered REGULAR BSR for single LCID=%d\n", pending_data_lcid);
return true; return true;
} else {
return false;
} }
} }
bool bsr_proc::check_all_channels() { }
void bsr_proc::update_pending_data() {
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
last_pending_data[i] = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
}
}
bool bsr_proc::generate_bsr(bsr_t *bsr, uint32_t nof_padding_bytes) {
bool ret = false; bool ret = false;
bzero(&pending_bsr, sizeof(bsr_t)); uint32_t nof_lcg=0;
bzero(bsr, sizeof(bsr_t));
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) { for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
if (lcg[i] >= 0) { if (lcg[i] >= 0) {
uint32_t n = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8; uint32_t n = mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pending_data()/8;
pending_bsr.buff_size[lcg[i]] += n; bsr->buff_size[lcg[i]] += n;
if (n > 0) { if (n > 0) {
nof_lcg++;
ret = true; 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 (triggered_bsr_type == PADDING) {
if (nof_padding_bytes < 4) { if (nof_padding_bytes < 4) {
// If space only for short // If space only for short
if (nof_lcg > 1) { if (nof_lcg > 1) {
pending_bsr.format = TRUNC_BSR; bsr->format = TRUNC_BSR;
uint32_t max_prio_ch = find_max_priority_lcid(); uint32_t max_prio_ch = find_max_priority_lcid();
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
if (lcg[max_prio_ch] != i) { if (lcg[max_prio_ch] != i) {
pending_bsr.buff_size[i] = 0; bsr->buff_size[i] = 0;
} }
} }
} else { } else {
pending_bsr.format = SHORT_BSR; bsr->format = SHORT_BSR;
} }
} else { } else {
// If space for long BSR // If space for long BSR
pending_bsr.format = LONG_BSR; bsr->format = LONG_BSR;
} }
} else { } else {
pending_bsr.format = SHORT_BSR; bsr->format = SHORT_BSR;
if (nof_lcg > 1) { if (nof_lcg > 1) {
pending_bsr.format = LONG_BSR; bsr->format = LONG_BSR;
} }
} }
return ret;
} }
// Checks if Regular BSR must be assembled, as defined in 5.4.5 // Checks if Regular BSR must be assembled, as defined in 5.4.5
@ -214,47 +214,87 @@ void bsr_proc::step(uint32_t tti)
} }
// Higher priority channel is reported regardless of a BSR being already triggered // Higher priority channel is reported regardless of a BSR being already triggered
check_highest_channel(); check_highest_channel();
}
bool bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t nof_padding_bytes, bsr_t *bsr) update_pending_data();
{ }
bool ret = false;
if (triggered_bsr_type == NONE) { char* bsr_proc::bsr_type_tostring(triggered_bsr_type_t type) {
// If enough space for at least truncated BSR switch(type) {
if (nof_padding_bytes >= 2) { case bsr_proc::REGULAR:
// Check condition 2 in Sec 5.4.5 return (char*) "Regular";
if (check_all_channels()) { case bsr_proc::PADDING:
triggered_bsr_type = PADDING; return (char*) "Padding";
case bsr_proc::PERIODIC:
return (char*) "Periodic";
} }
} }
char* bsr_proc::bsr_format_tostring(bsr_format_t format) {
switch(format) {
case bsr_proc::LONG_BSR:
return (char*) "Long";
case bsr_proc::SHORT_BSR:
return (char*) "Short";
case bsr_proc::TRUNC_BSR:
return (char*) "Truncated";
} }
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];
} }
Info("Triggered BSR: nof_grant_bytes=%d, nof_padding_bytes=%d, nof_pending_bytes=%d\n", nof_grant_bytes, nof_padding_bytes, nof_pending_bytes);
get_pending_bsr_format(nof_padding_bytes); uint32_t bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t grant_size)
{
uint32_t bsr_sz = 0;
if (triggered_bsr_type == PERIODIC || triggered_bsr_type == REGULAR) {
uint32_t total_data = 0;
/* Check if grant + MAC SDU headers is enough to accomodate all pending data */
for (int i=0;i<mac_io_h->NOF_UL_LCH && total_data < grant_size;i++) {
uint32_t idx = 0;
uint32_t sdu_len = 0;
while(mac_io_h->get(i+mac_io::MAC_LCH_CCCH_UL)->pop(&sdu_len, idx) && total_data < grant_size) {
idx++;
total_data += sch_pdu::size_plus_header_sdu(sdu_len/8);
}
}
total_data--; // Because last SDU has no size header
// Do not include BSR CE if the UL grant can accomodate all pending data but is not sufficient /* All triggered BSRs shall be cancelled in case the UL grant can accommodate all pending data available for transmission
// to additionally accomodate the BSR MAC CE plus its header but is not sufficient to additionally accommodate the BSR MAC control element plus its subheader.
uint32_t bsr_sz_plus_header = pending_bsr.format == LONG_BSR?4:2; */
if (nof_pending_bytes + bsr_sz_plus_header == nof_grant_bytes) { bsr_t bsr;
generate_bsr(&bsr, 0);
bsr_sz = bsr.format==LONG_BSR?3:1;
if (total_data <= grant_size && total_data + 1 + bsr_sz > grant_size) {
bsr_sz = 0;
Info("Grant is not enough to accomodate the BSR MAC CE\n");
triggered_bsr_type = NONE; triggered_bsr_type = NONE;
} else { }
// Instruct MUX unit to generate MAC CE Info("Checking if Regular BSR is sent: grant_size=%d, total_data=%d, bsr_sz=%d\n",
grant_size, total_data, bsr_sz);
}
return bsr_sz;
}
bool bsr_proc::generate_bsr_on_ul_grant(uint32_t nof_padding_bytes, bsr_t *bsr)
{
bool ret = false;
if (triggered_bsr_type != NONE || nof_padding_bytes >= 2) {
if (triggered_bsr_type == NONE) {
triggered_bsr_type = PADDING;
}
generate_bsr(bsr, nof_padding_bytes);
ret = true; ret = true;
memcpy(bsr, &pending_bsr, sizeof(bsr_t)); Info("Sending BSR type %s, format %s, nof_padding_bytes=%d\n",
if (timer_periodic && pending_bsr.format != TRUNC_BSR) { bsr_type_tostring(triggered_bsr_type), bsr_format_tostring(bsr->format), nof_padding_bytes);
if (timer_periodic && bsr->format != TRUNC_BSR) {
timers_db->get(mac::BSR_TIMER_PERIODIC)->reset(); timers_db->get(mac::BSR_TIMER_PERIODIC)->reset();
timers_db->get(mac::BSR_TIMER_PERIODIC)->run(); timers_db->get(mac::BSR_TIMER_PERIODIC)->run();
} }
// Cancel all triggered BSR // Cancel all triggered BSR
triggered_bsr_type = NONE; triggered_bsr_type = NONE;
} reset_sr = true;
} }
// Restart or Start ReTX timer // Restart or Start ReTX timer
@ -265,8 +305,18 @@ bool bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t n
return ret; return ret;
} }
bool bsr_proc::need_to_reset_sr() {
if (reset_sr) {
reset_sr = false;
return true;
} else {
return false;
}
}
bool bsr_proc::need_to_send_sr() { bool bsr_proc::need_to_send_sr() {
if (!sr_is_sent && triggered_bsr_type == REGULAR) { if (!sr_is_sent && triggered_bsr_type == REGULAR) {
reset_sr = false;
sr_is_sent = true; sr_is_sent = true;
return true; return true;
} }

@ -398,18 +398,17 @@ void ra_proc::step_contention_resolution() {
} else if (demux_unit->is_temp_crnti_pending()) } else if (demux_unit->is_temp_crnti_pending())
{ {
rInfo("MAC PDU with Temporal C-RNTI has been decoded\n"); rDebug("MAC PDU with Temporal C-RNTI has been decoded\n");
// Random Access initiated by RRC by the transmission of CCCH SDU // Random Access initiated by RRC by the transmission of CCCH SDU
if (demux_unit->is_contention_resolution_id_pending()) { if (demux_unit->is_contention_resolution_id_pending()) {
rInfo("MAC PDU Contains Contention Resolution ID CE\n"); rDebug("MAC PDU Contains Contention Resolution ID CE\n");
// MAC PDU successfully decoded and contains MAC CE contention Id // MAC PDU successfully decoded and contains MAC CE contention Id
uint64_t rx_contention_id = demux_unit->get_contention_resolution_id(); uint64_t rx_contention_id = demux_unit->get_contention_resolution_id();
timers_db->get(mac::CONTENTION_TIMER)->stop(); timers_db->get(mac::CONTENTION_TIMER)->stop();
if (transmitted_contention_id == rx_contention_id) { if (transmitted_contention_id == rx_contention_id) {
rInfo("MAC PDU Contention Resolution ID matches the one transmitted in CCCH SDU\n"); rDebug("MAC PDU Contention Resolution ID matches the one transmitted in CCCH SDU\n");
// UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3 // UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3
params_db->set_param(mac_params::RNTI_C, params_db->get_param(mac_params::RNTI_TEMP)); params_db->set_param(mac_params::RNTI_C, params_db->get_param(mac_params::RNTI_TEMP));
// finish the disassembly and demultiplexing of the MAC PDU // finish the disassembly and demultiplexing of the MAC PDU
demux_unit->demultiplex_pending_pdu(); demux_unit->demultiplex_pending_pdu();
state = COMPLETION; state = COMPLETION;

@ -42,6 +42,7 @@ void sr_proc::init(log* log_h_, mac_params* params_db_, phy* phy_h_)
params_db = params_db_; params_db = params_db_;
phy_h = phy_h_; phy_h = phy_h_;
initiated = true; initiated = true;
do_ra = false;
} }
void sr_proc::reset() void sr_proc::reset()
@ -54,11 +55,20 @@ void sr_proc::step(uint32_t tti)
{ {
if (initiated) { if (initiated) {
if (is_pending_sr) { if (is_pending_sr) {
if (params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) {
if (sr_counter < dsr_transmax) { if (sr_counter < dsr_transmax) {
int last_tx_tti = phy_h->sr_last_tx_tti();
if (last_tx_tti >= 0 && last_tx_tti + 4 < tti) {
sr_counter++; sr_counter++;
Info("SR stepping: sr_counter=%d\n", sr_counter); Info("SR signalling PHY. sr_counter=%d, PHY TTI=%d\n", sr_counter, phy_h->get_current_tti());
phy_h->send_sr(true); phy_h->send_sr(true);
}
} else {
do_ra = true;
reset();
}
} else { } else {
do_ra = true;
reset(); reset();
} }
} }
@ -67,10 +77,8 @@ void sr_proc::step(uint32_t tti)
bool sr_proc::need_random_access() { bool sr_proc::need_random_access() {
if (initiated) { if (initiated) {
if (sr_counter == dsr_transmax && dsr_transmax > 0 && if (do_ra) {
params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) { do_ra = false;
Info("SR checking need RA: sr_counter=%d, dsr_transmax=%d, configured=%d\n", sr_counter, dsr_transmax, params_db->get_param(mac_params::SR_PUCCH_CONFIGURED));
return true; return true;
} else { } else {
return false; return false;
@ -81,14 +89,12 @@ bool sr_proc::need_random_access() {
void sr_proc::start() void sr_proc::start()
{ {
if (initiated) { if (initiated) {
if (params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) {
if (!is_pending_sr) { if (!is_pending_sr) {
sr_counter = 0; sr_counter = 0;
is_pending_sr = true; is_pending_sr = true;
dsr_transmax = params_db->get_param(mac_params::SR_TRANS_MAX);
Info("SR starting dsrTransMax=%d. Setting sr_counter=0\n", dsr_transmax);
}
} }
dsr_transmax = params_db->get_param(mac_params::SR_TRANS_MAX);
Info("SR starting dsrTransMax=%d. sr_counter=%d, PHY TTI=%d\n", dsr_transmax, sr_counter, phy_h->get_current_tti());
} }
} }

@ -239,14 +239,14 @@ void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, uint8_t *
{ {
if (ul_grant && pdu_payload) { if (ul_grant && pdu_payload) {
srslte_softbuffer_tx_reset(&softbuffer); srslte_softbuffer_tx_reset(&softbuffer);
// Store the uplink grant
memcpy(&cur_grant, ul_grant, sizeof(ul_sched_grant)); memcpy(&cur_grant, ul_grant, sizeof(ul_sched_grant));
harq_feedback = false; harq_feedback = false;
is_grant_configured = true; is_grant_configured = true;
current_tx_nb = 0; current_tx_nb = 0;
current_irv = 0; current_irv = 0;
is_msg3 = is_msg3_; is_msg3 = is_msg3_;
Info("UL PID %d: New TX%s, RV=%d, TBS=%d, MCS=%d\n", pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.get_tbs(), cur_grant.get_mcs()); Info("UL PID %d: New TX%s, RV=%d, TBS=%d, MCS=%d, RNTI=%d\n", pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.get_tbs(),
cur_grant.get_mcs(), cur_grant.get_rnti());
generate_tx(tti_tx, pdu_payload, ul); generate_tx(tti_tx, pdu_payload, ul);
} }
} }

@ -24,5 +24,5 @@ FIND_PACKAGE(openLTE)
IF(UHD_FOUND AND OPENLTE_FOUND) IF(UHD_FOUND AND OPENLTE_FOUND)
INCLUDE_DIRECTORIES(${OPENLTE_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${OPENLTE_INCLUDE_DIRS})
ADD_EXECUTABLE(mac_test mac_test.cc) ADD_EXECUTABLE(mac_test mac_test.cc)
TARGET_LINK_LIBRARIES(mac_test srsapps_ue_mac srsapps_ue_phy srsapps_radio srslte ${OPENLTE_LIBRARIES} srslte_uhd) TARGET_LINK_LIBRARIES(mac_test srsapps_common srsapps_ue_mac srsapps_ue_phy srsapps_radio srslte ${OPENLTE_LIBRARIES} srslte_uhd)
ENDIF(UHD_FOUND AND OPENLTE_FOUND) ENDIF(UHD_FOUND AND OPENLTE_FOUND)

@ -199,37 +199,39 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
} }
void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac *mac, srslte::ue::phy *phy) { void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac *mac, srslte::ue::phy *phy) {
mac->set_param(srslte::ue::mac_params::HARQ_MAXTX,
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx]); // FIXME: There's an error parsing the connectionSetup message. This value is hard-coded:
printf("Set MAX HARQ reTX: %d\n", liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx]); msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx = 35;
phy->set_param(srslte::ue::phy_params::SR_PUCCH_RESINDEX, phy->set_param(srslte::ue::phy_params::SR_PUCCH_RESINDEX,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx); msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx);
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX, phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx); msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
printf("Set PHY configuration: n_pucch=%d, configIndex=%d\n",
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
mac->set_param(srslte::ue::mac_params::HARQ_MAXTX,
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx]);
mac->set_param(srslte::ue::mac_params::SR_TRANS_MAX, mac->set_param(srslte::ue::mac_params::SR_TRANS_MAX,
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max]); liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max]);
mac->set_param(srslte::ue::mac_params::SR_PUCCH_CONFIGURED, 1); mac->set_param(srslte::ue::mac_params::SR_PUCCH_CONFIGURED, 1);
printf("Set SR configuration: TransMAX: %d, n_pucch=%d, configIndex=%d\n",
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max],
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
mac->set_param(srslte::ue::mac_params::BSR_TIMER_RETX, mac->set_param(srslte::ue::mac_params::BSR_TIMER_RETX,
liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer]); liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer]);
mac->set_param(srslte::ue::mac_params::BSR_TIMER_PERIODIC, mac->set_param(srslte::ue::mac_params::BSR_TIMER_PERIODIC,
liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]); liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]);
printf("Set MAC BSR configuration: ReTX timer: %d, Periodic: %d\n", printf("Set MAC configuration: dsr-TransMAX: %d, harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n",
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max],
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx],
liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer], liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer],
liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]); liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
// Setup radio bearers // Setup radio bearers
for (int i=0;i<msg->rr_cnfg.srb_to_add_mod_list_size;i++) { for (int i=0;i<msg->rr_cnfg.srb_to_add_mod_list_size;i++) {
@ -254,18 +256,17 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac
// Hex bytes for the connection setup complete packet // Hex bytes for the connection setup complete packet
// Got hex bytes from http://www.sharetechnote.com/html/RACH_LTE.html // Got hex bytes from http://www.sharetechnote.com/html/RACH_LTE.html
uint8_t setupComplete_segm[10][12] ={{0x88, 0x00, 0x00, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, uint8_t setupComplete_segm[2][41] ={ {
{0x98, 0x01, 0x20, 0x80, 0x01, 0x00, 0x59, 0x17, 0x0, 0x0, 0x0, 0x0}, 0x88, 0x00, 0x00, 0x20, 0x21, 0x90, 0xa0, 0x12, 0x00, 0x00, 0x80, 0xf0, 0x5e, 0x3b, 0xf1, 0x04,
{0x98, 0x02, 0x39, 0x45, 0xE5, 0x34, 0x0B, 0x07, 0x0, 0x0, 0x0, 0x0}, 0x64, 0x04, 0x1d, 0x20, 0x44, 0x2f, 0xd8, 0x4b, 0xd1, 0x02, 0x00, 0x00, 0x83, 0x03, 0x41, 0xb0,
{0x98, 0x03, 0x41, 0x02, 0x0B, 0xF6, 0x03, 0x02, 0x0, 0x0, 0x0, 0x0}, 0xe5, 0x60, 0x13, 0x81, 0x83},
{0x98, 0x04, 0x27, 0x80, 0x01, 0x00, 0xD0, 0xCC, 0x0, 0x0, 0x0, 0x0},
{0x98, 0x05, 0x71, 0x51, 0x04, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, {0xb0, 0x01, 0x01, 0x01, 0x48, 0x4b, 0xd1, 0x00, 0x7d, 0x21, 0x70, 0x28, 0x01, 0x5c, 0x08, 0x80,
{0x98, 0x06, 0xE0, 0xC0, 0x40, 0x00, 0x21, 0x02, 0x0, 0x0, 0x0, 0x0}, 0x00, 0xc4, 0x0f, 0x97, 0x80, 0xd0, 0x4c, 0x4b, 0xd1, 0x00, 0xc0, 0x58, 0x44, 0x0d, 0x5d, 0x62,
{0x98, 0x07, 0x03, 0xD0, 0x11, 0xD1, 0x27, 0x1A, 0x0, 0x0, 0x0, 0x0}, 0x99, 0x74, 0x04, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00}
{0x98, 0x08, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x0, 0x0, 0x0, 0x0}, };
{0xB0, 0x09, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06}}; uint32_t lengths[2] = {37, 41};
uint8_t last_segm[54]; uint8_t reply[2] = {0x00, 0x04};
uint32_t lengths[10] = {4, 8, 8, 8, 8, 6, 8, 8, 8, 12};
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -316,7 +317,7 @@ int main(int argc, char *argv[])
uint32_t si_window_len, sib2_period; uint32_t si_window_len, sib2_period;
int tti; int tti;
enum {START, SIB1, SIB2, CONNECT, SETUPCOMPLETE} state = START; enum {START, SIB1, SIB2, CONNECT, SETUPCOMPLETE, IDLE} state = START;
int n; int n;
while(1) { while(1) {
@ -359,7 +360,7 @@ int main(int argc, char *argv[])
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ;
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE; ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE;
ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000; ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000;
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_DATA; ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING;
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg); liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg);
uint64_t uecri=0; uint64_t uecri=0;
@ -395,26 +396,15 @@ int main(int argc, char *argv[])
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy); process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy);
// Generate and send ConnectionSetupComplete // Generate and send ConnectionSetupComplete
for (int i=0;i<9;i++) { for (int i=0;i<2;i++) {
printf("Sending Connection Setup Complete %d\n", i); printf("Sending Connection Setup Complete %d\n", i);
srslte_bit_pack_vector(setupComplete_segm[i], bit_msg.msg, lengths[i]); srslte_bit_pack_vector(setupComplete_segm[i], bit_msg.msg, lengths[i]*8);
n=mac.send_dcch0_sdu(bit_msg.msg, lengths[i]*8); n=mac.send_dcch0_sdu(bit_msg.msg, lengths[i]*8);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error writting to DCCH0\n"); fprintf(stderr, "Error writting to DCCH0\n");
exit(-1); exit(-1);
} }
} }
// Last segment is 54 bytes long
printf("Sending Connection Setup Complete Last segment\n");
bzero(last_segm, 54*sizeof(uint8_t));
memcpy(last_segm, setupComplete_segm[9], lengths[9]*sizeof(uint8_t));
srslte_bit_pack_vector(last_segm, bit_msg.msg, 54);
n=mac.send_dcch0_sdu(bit_msg.msg, 54*8);
if (n < 0) {
fprintf(stderr, "Error writting to DCCH0\n");
exit(-1);
}
state = SETUPCOMPLETE; state = SETUPCOMPLETE;
break; break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ: case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
@ -426,11 +416,21 @@ int main(int argc, char *argv[])
break; break;
case SETUPCOMPLETE: case SETUPCOMPLETE:
// Wait for ConnectionSetup // Wait for ConnectionSetup
n = mac.recv_dtch0_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); n = mac.recv_dcch0_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
if (n > 0) { if (n > 0) {
printf("Received on DTCH0 %d bytes\n", n/8); printf("Received on DCCH0 %d bytes\n", n/8);
printf("Send RLC ACK\n");
srslte_bit_pack_vector(reply, bit_msg.msg, 2*8);
n=mac.send_dcch0_sdu(bit_msg.msg, 2*8);
if (n < 0) {
fprintf(stderr, "Error writting to DCCH0\n");
exit(-1);
}
state = IDLE;
} }
break; break;
case IDLE:
break;
} }
usleep(10000); usleep(10000);

@ -27,7 +27,6 @@ INSTALL(DIRECTORY include/
FILE(GLOB SOURCES "src/*.cc") FILE(GLOB SOURCES "src/*.cc")
ADD_LIBRARY(srsapps_ue_phy SHARED ${SOURCES}) ADD_LIBRARY(srsapps_ue_phy SHARED ${SOURCES})
TARGET_LINK_LIBRARIES(srsapps_ue_phy srsapps_common)
INSTALL(TARGETS srsapps_ue_phy DESTINATION ${LIBRARY_DIR}) INSTALL(TARGETS srsapps_ue_phy DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srsapps_ue_phy) SRSLTE_SET_PIC(srsapps_ue_phy)

@ -50,6 +50,7 @@ namespace ue {
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h_); bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h_);
void free_cell(); void free_cell();
void set_crnti(uint16_t rnti);
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time); bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time);
bool get_ul_grant(ul_sched_grant *grant); bool get_ul_grant(ul_sched_grant *grant);
bool get_dl_grant(dl_sched_grant *grant); bool get_dl_grant(dl_sched_grant *grant);

@ -81,6 +81,8 @@ public:
float get_agc_gain(); float get_agc_gain();
void set_crnti(uint16_t rnti);
// Indicate the PHY to send PRACH as soon as possible // Indicate the PHY to send PRACH as soon as possible
bool init_prach(); bool init_prach();
bool send_prach(uint32_t preamble_idx); bool send_prach(uint32_t preamble_idx);
@ -89,6 +91,7 @@ public:
// Indicate the PHY to send SR as soon as possible or not // Indicate the PHY to send SR as soon as possible or not
void send_sr(bool enable); void send_sr(bool enable);
int sr_last_tx_tti();
// Returns TTI when PRACH was transmitted. -1 if not yet transmitted // Returns TTI when PRACH was transmitted. -1 if not yet transmitted
int get_prach_transmitted_tti(); int get_prach_transmitted_tti();
@ -162,6 +165,7 @@ private:
void run_rx_tx_state(); void run_rx_tx_state();
ul_buffer* get_ul_buffer_adv(uint32_t tti); ul_buffer* get_ul_buffer_adv(uint32_t tti);
float old_gain; float old_gain;
uint32_t sr_tx_tti;
}; };

@ -49,6 +49,7 @@ namespace ue {
public: public:
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h); bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h);
void free_cell(); void free_cell();
void set_crnti(uint16_t rnti);
void set_current_tx_nb(uint32_t current_tx_nb); void set_current_tx_nb(uint32_t current_tx_nb);
bool generate_ack(bool ack, dl_sched_grant *last_dl_grant); bool generate_ack(bool ack, dl_sched_grant *last_dl_grant);
bool generate_ack(bool ack[2]); bool generate_ack(bool ack[2]);

@ -65,6 +65,11 @@ void dl_buffer::free_cell()
srslte_ue_dl_free(&ue_dl); srslte_ue_dl_free(&ue_dl);
} }
void dl_buffer::set_crnti(uint16_t rnti)
{
srslte_ue_dl_set_rnti(&ue_dl, rnti);
}
// FIXME: Avoid this memcpy modifying ue_sync to directly write into provided pointer // FIXME: Avoid this memcpy modifying ue_sync to directly write into provided pointer
bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time) bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time)
{ {
@ -111,7 +116,6 @@ bool dl_buffer::get_ul_grant(ul_sched_grant *grant)
if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) { if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) {
return false; return false;
} }
return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET)); return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
} }
} }
@ -161,6 +165,8 @@ bool dl_buffer::get_dl_grant(dl_sched_grant *grant)
return false; return false;
} }
Info("Found DL DCI cce_index=%d, n_data_bits=%d\n", ue_dl.last_n_cce, dci_msg.nof_bits);
return grant->create_from_dci(&dci_msg, cell, cfi, tti%10, srslte_ue_dl_get_ncce(&ue_dl)); return grant->create_from_dci(&dci_msg, cell, cfi, tti%10, srslte_ue_dl_get_ncce(&ue_dl));
} }
} }

@ -29,9 +29,11 @@
#include <strings.h> #include <strings.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h>
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srsapps/common/threads.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/prach.h" #include "srsapps/ue/phy/prach.h"
@ -57,8 +59,12 @@ bool phy::init_agc(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_
return init_(radio_handler_, ttisync_, log_h, true); return init_(radio_handler_, ttisync_, log_h, true);
} }
bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h_, bool do_agc_) bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h_, bool do_agc_)
{ {
mlockall(MCL_CURRENT | MCL_FUTURE);
started = false; started = false;
radio_is_streaming = false; radio_is_streaming = false;
ttisync = ttisync_; ttisync = ttisync_;
@ -74,18 +80,9 @@ bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, l
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160); params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160);
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100); params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100);
pthread_attr_t attr; if (threads_new_rt(&phy_thread, phy_thread_fnc, this)) {
struct sched_param param;
param.sched_priority = sched_get_priority_min(SCHED_FIFO) ;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
if (!pthread_create(&phy_thread, &attr, phy_thread_fnc, this)) {
started = true; started = true;
} else {
perror("pthread_create");
} }
pthread_attr_destroy(&attr);
return started; return started;
} }
@ -186,14 +183,25 @@ void phy::send_sr(bool enable)
} }
sr_n_pucch = params_db.get_param(phy_params::SR_PUCCH_RESINDEX); sr_n_pucch = params_db.get_param(phy_params::SR_PUCCH_RESINDEX);
Info("SR I_sr=%d, periodicity=%d, N_offset=%d, n_pucch=%d\n", I_sr, sr_periodicity, sr_N_offset, sr_n_pucch); Info("SR I_sr=%d, periodicity=%d, N_offset=%d, n_pucch=%d\n", I_sr, sr_periodicity, sr_N_offset, sr_n_pucch);
sr_tx_tti = get_current_tti();
} }
sr_enabled = enable; sr_enabled = enable;
} }
int phy::sr_last_tx_tti() {
if (sr_enabled) {
return -1;
} else {
return (int) sr_tx_tti;
}
}
bool phy::sr_is_ready_to_send(uint32_t tti_) { bool phy::sr_is_ready_to_send(uint32_t tti_) {
if (sr_enabled) { if (sr_enabled) {
if ((10*tti_to_SFN(tti_)+tti_to_subf(tti_)-sr_N_offset)%sr_periodicity==0) { if ((10*tti_to_SFN(tti_)+tti_to_subf(tti_)-sr_N_offset)%sr_periodicity==0) {
Info("SR ready to send\n"); sr_enabled = false;
sr_tx_tti = tti_;
Debug("SR ready to send for TTI=%d\n", tti_);
return true; return true;
} }
} }
@ -214,6 +222,14 @@ bool phy::measure()
return false; return false;
} }
void phy::set_crnti(uint16_t rnti) {
for(uint32_t i=0;i<6;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->set_crnti(rnti);
((dl_buffer*) dl_buffer_queue->get(i))->set_crnti(rnti);
}
}
bool phy::start_rxtx() bool phy::start_rxtx()
{ {
if (phy_state == IDLE) { if (phy_state == IDLE) {
@ -328,6 +344,9 @@ bool phy::init_prach() {
ul_buffer* phy::get_ul_buffer(uint32_t tti) ul_buffer* phy::get_ul_buffer(uint32_t tti)
{ {
if (tti + 1 < get_current_tti()) {
Warning("Warning access to PHY UL buffer too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti());
}
return (ul_buffer*) ul_buffer_queue->get(tti); return (ul_buffer*) ul_buffer_queue->get(tti);
} }
@ -339,7 +358,8 @@ ul_buffer* phy::get_ul_buffer_adv(uint32_t tti)
dl_buffer* phy::get_dl_buffer(uint32_t tti) dl_buffer* phy::get_dl_buffer(uint32_t tti)
{ {
if (tti + 4 < get_current_tti()) { if (tti + 4 < get_current_tti()) {
Debug("Warning access to PHY too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti()); Warning("Warning access to PHY DL buffer too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti());
// return NULL;
} }
return (dl_buffer*) dl_buffer_queue->get(tti); return (dl_buffer*) dl_buffer_queue->get(tti);
} }

@ -47,6 +47,7 @@ bool ul_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_
params_db = params_db_; params_db = params_db_;
current_tx_nb = 0; current_tx_nb = 0;
if (!srslte_ue_ul_init(&ue_ul, cell)) { if (!srslte_ue_ul_init(&ue_ul, cell)) {
srslte_ue_ul_set_normalization(&ue_ul, false);
signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
cell_initiated = signal_buffer?true:false; cell_initiated = signal_buffer?true:false;
srslte_ue_ul_set_cfo_enable(&ue_ul, false); srslte_ue_ul_set_cfo_enable(&ue_ul, false);
@ -67,6 +68,11 @@ void ul_buffer::free_cell() {
} }
} }
void ul_buffer::set_crnti(uint16_t rnti)
{
srslte_ue_ul_set_rnti(&ue_ul, rnti);
}
bool ul_buffer::generate_ack(bool ack, dl_sched_grant *last_dl_grant) bool ul_buffer::generate_ack(bool ack, dl_sched_grant *last_dl_grant)
{ {
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
@ -96,7 +102,7 @@ bool ul_buffer::generate_cqi_report()
bool ul_buffer::generate_sr() { bool ul_buffer::generate_sr() {
uci_data.scheduling_request = true; uci_data.scheduling_request = true;
uci_pending = true; uci_pending = true;
Info("SR Generating\n"); Debug("SR Generating\n");
return true; return true;
} }
@ -113,6 +119,8 @@ bool ul_buffer::generate_data(ul_sched_grant *grant,
{ {
generate_data(grant, &ue_ul.softbuffer, payload); generate_data(grant, &ue_ul.softbuffer, payload);
} }
//int nof_tx=0;
bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload) bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload)
{ {
@ -128,6 +136,13 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
dmrs_cfg.cyclic_shift = params_db->get_param(phy_params::PUSCH_RS_CYCLIC_SHIFT); dmrs_cfg.cyclic_shift = params_db->get_param(phy_params::PUSCH_RS_CYCLIC_SHIFT);
dmrs_cfg.delta_ss = params_db->get_param(phy_params::PUSCH_RS_GROUP_ASSIGNMENT); dmrs_cfg.delta_ss = params_db->get_param(phy_params::PUSCH_RS_GROUP_ASSIGNMENT);
// Get cyclic shift for DMRS if PUSCH is not for RAR or (TODO) is not SPS
if (grant) {
if (!grant->is_from_rar()) {
dmrs_cfg.en_dmrs_2 = true;
dmrs_cfg.cyclic_shift_for_dmrs = grant->get_n_dmrs();
}
}
srslte_pusch_hopping_cfg_t pusch_hopping; srslte_pusch_hopping_cfg_t pusch_hopping;
if (grant) { if (grant) {
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t)); bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t));
@ -168,17 +183,20 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
// Transmit on PUSCH if UL grant available, otherwise in PUCCH // Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (grant) { if (grant) {
INFO("Encoding PUSCH TBS=%d, rb_start=%d n_prb=%d, rv=%d, rnti=%d\n",
grant->get_tbs(), pusch_cfg.grant.L_prb, pusch_cfg.grant.n_prb[0], grant->get_rv(), grant->get_rnti());
grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg); grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg);
Info("Encoding PUSCH TBS=%d, mod=%s, rb_start=%d n_prb=%d, ack=%s, sr=%s, rnti=%d, sf_idx=%d\n",
grant->get_tbs(), srslte_mod_string(pusch_cfg.grant.mcs.mod), pusch_cfg.grant.n_prb[0], pusch_cfg.grant.L_prb,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",uci_data.scheduling_request?"yes":"no",
grant->get_rnti(), tti%10);
n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg, n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg,
payload, uci_data, payload, uci_data,
softbuffer, softbuffer,
grant->get_rnti(), grant->get_rnti(),
signal_buffer); signal_buffer);
} else { } else {
Info("Encoding PUCCH n_cce=%d, ack=%d\n", last_n_cce, uci_data.uci_ack); Info("Encoding PUCCH n_cce=%d, ack=%d, sr=%d\n", last_n_cce, uci_data.uci_ack, uci_data.scheduling_request);
n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer); n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer);
} }
@ -198,6 +216,8 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
} }
} }
int nof_tx = 0;
bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time) bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time)
{ {
// send packet through usrp // send packet through usrp
@ -217,18 +237,22 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo
} }
} }
Info("TX CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us PeakAmplitude=%.2f\n", // Normalize before TX
srslte_vec_sc_prod_cfc(signal_buffer, 0.9/max, signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
Info("TX CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us PeakAmplitude=%.2f PKT#%d\n",
cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb), cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb),
srslte_timestamp_real(&rx_time), srslte_timestamp_real(&rx_time),
srslte_timestamp_real(&tx_time), time_adv_sec*1000000, max); srslte_timestamp_real(&tx_time), time_adv_sec*1000000, max, nof_tx);
if (max > 1.0) {
srslte_vec_save_file((char*) "first_pusch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time); radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time);
//srslte_vec_save_file("pucch_tx", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
char filename[25];
sprintf(filename, "pusch%d",nof_tx);
srslte_vec_save_file(filename, signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
nof_tx++;
ready(); ready();
} }

@ -22,8 +22,8 @@
IF(UHD_FOUND) IF(UHD_FOUND)
ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc) ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc)
TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srsapps_ue_phy srsapps_radio srslte srslte_uhd) TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ADD_EXECUTABLE(ue_itf_test_prach ue_itf_test_prach.cc) ADD_EXECUTABLE(ue_itf_test_prach ue_itf_test_prach.cc)
TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_ue_phy srsapps_radio srslte srslte_uhd) TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ENDIF(UHD_FOUND) ENDIF(UHD_FOUND)

@ -169,6 +169,7 @@ typedef struct SRSLTE_API {
uint32_t n_dmrs; uint32_t n_dmrs;
bool ndi; bool ndi;
bool cqi_request; bool cqi_request;
uint32_t tpc_pusch;
} srslte_ra_ul_dci_t; } srslte_ra_ul_dci_t;

@ -266,7 +266,7 @@ bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_re
void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, cf_t *r_pusch, uint32_t nof_prb, uint32_t n_prb[2], cf_t *sf_symbols) void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, cf_t *r_pusch, uint32_t nof_prb, uint32_t n_prb[2], cf_t *sf_symbols)
{ {
for (uint32_t ns_idx=0;ns_idx<2;ns_idx++) { for (uint32_t ns_idx=0;ns_idx<2;ns_idx++) {
DEBUG("Putting DRMS to n_prb: %d, L: %d, ns_idx: %d\n", n_prb[ns_idx], nof_prb, ns_idx); INFO("Putting DRMS to n_prb: %d, L: %d, ns_idx: %d\n", n_prb[ns_idx], nof_prb, ns_idx);
uint32_t L = (ns_idx+1)*SRSLTE_CP_NSYMB(q->cell.cp)-4; uint32_t L = (ns_idx+1)*SRSLTE_CP_NSYMB(q->cell.cp)-4;
memcpy(&sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, L, n_prb[ns_idx]*SRSLTE_NRE)], memcpy(&sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, L, n_prb[ns_idx]*SRSLTE_NRE)],
&r_pusch[ns_idx*SRSLTE_NRE*nof_prb], nof_prb*SRSLTE_NRE*sizeof(cf_t)); &r_pusch[ns_idx*SRSLTE_NRE*nof_prb], nof_prb*SRSLTE_NRE*sizeof(cf_t));

@ -127,9 +127,9 @@ char *srslte_mod_string(srslte_mod_t mod) {
case SRSLTE_MOD_QPSK: case SRSLTE_MOD_QPSK:
return "QPSK"; return "QPSK";
case SRSLTE_MOD_16QAM: case SRSLTE_MOD_16QAM:
return "QAM16"; return "16QAM";
case SRSLTE_MOD_64QAM: case SRSLTE_MOD_64QAM:
return "QAM64"; return "64QAM";
default: default:
return "N/A"; return "N/A";
} }

@ -122,10 +122,12 @@ double cuhd_set_rx_gain_th(void *h, double gain)
{ {
cuhd_handler *handler = static_cast < cuhd_handler * >(h); cuhd_handler *handler = static_cast < cuhd_handler * >(h);
gain = handler->rx_gain_range.clip(gain); gain = handler->rx_gain_range.clip(gain);
if (gain != handler->new_rx_gain) {
pthread_mutex_lock(&handler->mutex); pthread_mutex_lock(&handler->mutex);
handler->new_rx_gain = gain; handler->new_rx_gain = gain;
pthread_cond_signal(&handler->cond); pthread_cond_signal(&handler->cond);
pthread_mutex_unlock(&handler->mutex); pthread_mutex_unlock(&handler->mutex);
}
return gain; return gain;
} }

@ -414,9 +414,11 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t
data->ndi = *y++ ? true : false; data->ndi = *y++ ? true : false;
// TPC and DM RS commands not implemented // TPC command for scheduled PUSCH
y += 5; data->tpc_pusch = srslte_bit_unpack(&y, 2);
data->n_dmrs = 0;
// Cyclic shift for DMRS
data->n_dmrs = srslte_bit_unpack(&y, 3);
// CQI request // CQI request
data->cqi_request = *y++ ? true : false; data->cqi_request = *y++ ? true : false;

@ -283,6 +283,7 @@ static int dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t E, ui
E <= q->max_bits && E <= q->max_bits &&
nof_bits <= SRSLTE_DCI_MAX_BITS) nof_bits <= SRSLTE_DCI_MAX_BITS)
{ {
bzero(q->rm_f, sizeof(float)*3 * (SRSLTE_DCI_MAX_BITS + 16));
/* unrate matching */ /* unrate matching */
srslte_rm_conv_rx(e, E, q->rm_f, 3 * (nof_bits + 16)); srslte_rm_conv_rx(e, E, q->rm_f, 3 * (nof_bits + 16));
@ -315,7 +316,11 @@ static int dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t E, ui
* The decoded message is stored in msg and the CRC remainder in crc_rem pointer * The decoded message is stored in msg and the CRC remainder in crc_rem pointer
* *
*/ */
int srslte_pdcch_decode_msg(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_location_t *location, srslte_dci_format_t format, uint16_t *crc_rem) int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
srslte_dci_msg_t *msg,
srslte_dci_location_t *location,
srslte_dci_format_t format,
uint16_t *crc_rem)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
@ -334,11 +339,20 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci
DEBUG("Decoding DCI offset %d, e_bits: %d, msg_len %d (nCCE: %d, L: %d)\n", DEBUG("Decoding DCI offset %d, e_bits: %d, msg_len %d (nCCE: %d, L: %d)\n",
location->ncce * 72, e_bits, nof_bits, location->ncce, location->L); location->ncce * 72, e_bits, nof_bits, location->ncce, location->L);
double mean = 0;
for (int i=0;i<e_bits;i++) {
mean += fabsf(q->llr[location->ncce * 72 + i]);
}
mean /= e_bits;
if (mean > 0.5) {
ret = dci_decode(q, &q->llr[location->ncce * 72], ret = dci_decode(q, &q->llr[location->ncce * 72],
msg->data, e_bits, nof_bits, crc_rem); msg->data, e_bits, nof_bits, crc_rem);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
msg->nof_bits = nof_bits; msg->nof_bits = nof_bits;
} }
} else {
ret = SRSLTE_SUCCESS;
}
} }
} }
return ret; return ret;
@ -368,6 +382,7 @@ int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLT
uint32_t e_bits = 72*q->nof_cce; uint32_t e_bits = 72*q->nof_cce;
nof_symbols = e_bits/2; nof_symbols = e_bits/2;
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q->llr, sizeof(float) * q->max_bits);
DEBUG("Extracting LLRs: E: %d, SF: %d, CFI: %d\n", DEBUG("Extracting LLRs: E: %d, SF: %d, CFI: %d\n",
e_bits, nsubframe, cfi); e_bits, nsubframe, cfi);

@ -265,9 +265,16 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
fprintf(stderr, "Error decoding DCI msg\n"); fprintf(stderr, "Error decoding DCI msg\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (dci_msg->data[0] != 0) {
crc_rem = 0;
}
DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem); DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
} }
return crc_rem == rnti; if (crc_rem == rnti) {
return 1;
} else {
return 0;
}
} }
uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) { uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) {
@ -301,10 +308,19 @@ int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
fprintf(stderr, "Error decoding DCI msg\n"); fprintf(stderr, "Error decoding DCI msg\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (formats[f] == SRSLTE_DCI_FORMAT1A) {
if (dci_msg->data[0] != 1) {
crc_rem = 0;
}
}
DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem); DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
} }
} }
return crc_rem == rnti; if (crc_rem == rnti) {
return 1;
} else {
return 0;
}
} }

@ -265,7 +265,6 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
} }
srslte_refsignal_dmrs_pucch_put(&q->dmrs, format, n_pucch, q->refsignal, q->sf_symbols); srslte_refsignal_dmrs_pucch_put(&q->dmrs, format, n_pucch, q->refsignal, q->sf_symbols);
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
if (q->cfo_en) { if (q->cfo_en) {
@ -339,6 +338,7 @@ int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
bzero(q->sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
if (q != NULL && if (q != NULL &&
cfg != NULL && cfg != NULL &&

Loading…
Cancel
Save