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,20 +47,42 @@ 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,53 +67,50 @@ 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
@ -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";
} }
}
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
/* All triggered BSRs shall be cancelled in case the UL grant can accommodate all pending data available for transmission
but is not sufficient to additionally accommodate the BSR MAC control element plus its subheader.
*/
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;
} }
if (triggered_bsr_type != NONE) { Info("Checking if Regular BSR is sent: grant_size=%d, total_data=%d, bsr_sz=%d\n",
// If no more data is pending and there is no space for MAC CE grant_size, total_data, bsr_sz);
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); return bsr_sz;
}
bool bsr_proc::generate_bsr_on_ul_grant(uint32_t nof_padding_bytes, bsr_t *bsr)
{
bool ret = false;
get_pending_bsr_format(nof_padding_bytes); if (triggered_bsr_type != NONE || nof_padding_bytes >= 2) {
// 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 if (triggered_bsr_type == NONE) {
uint32_t bsr_sz_plus_header = pending_bsr.format == LONG_BSR?4:2; triggered_bsr_type = PADDING;
if (nof_pending_bytes + bsr_sz_plus_header == nof_grant_bytes) { }
triggered_bsr_type = NONE; generate_bsr(bsr, nof_padding_bytes);
} else {
// Instruct MUX unit to generate MAC CE
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[])
@ -290,7 +291,7 @@ int main(int argc, char *argv[])
break; break;
} }
// Init Radio and PHY // Init Radio and PHY
if (prog_args.uhd_rx_gain > 0 && prog_args.uhd_tx_gain > 0) { if (prog_args.uhd_rx_gain > 0 && prog_args.uhd_tx_gain > 0) {
radio_uhd.init(); radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_rx_gain); radio_uhd.set_rx_gain(prog_args.uhd_rx_gain);
@ -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