Working on mac_test

master
ismagom 10 years ago
parent 881a90d62c
commit 68d193a725

@ -1,12 +1,18 @@
function cfo = cfo_estimate_cp(input, Nsyms, sym_len, cp0_len, cp_len) function cfo = cfo_estimate_cp(input_slot, Nsyms, sym_len, cp0_len, cp_len)
r=zeros(Nsyms, 1); % Start correlating from the end. Nsyms is the number of symbols to
r(1)=sum(input(1:cp0_len).*conj(input(1+sym_len:cp0_len+sym_len))); % correlate starting from the end.
s=cp0_len+sym_len+1;
e=cp0_len+sym_len+cp_len; s=length(input_slot)-sym_len-cp_len;
for i=2:Nsyms e=length(input_slot)-sym_len;
r(i)=sum(input(s:e).*conj(input(s+sym_len:e+sym_len))); for i=1:Nsyms
s=s+sym_len+cp_len; r(i)=sum(input_slot(s:e).*conj(input_slot(s+sym_len:e+sym_len)));
e=e+sym_len+cp_len; if (i < 7)
s=s-sym_len-cp_len;
e=e-sym_len-cp_len;
else
s=s-sym_len-cp0_len;
e=e-sym_len-cp0_len;
end
end end
cfo=-angle(mean(r))/2/pi; cfo=-angle(mean(r))/pi;

@ -1,27 +1,21 @@
%clear; clear;
M=1000;
sym_len=128; sym_len=128;
x=lte(1:M*15360*sym_len/2048*2000/1536); hflen = (sym_len/128)*1920*10;
%x=read_complex('../../../eclipse_osldlib/test.dat'); N_id_2=1;
%y=resample(x,99839996,100000000); input=read_complex('../../build/lte_signal.dat', hflen*500);
input=resample(x,1536,2000);
%input=x;
%input=y(1:M*15360*sym_len/2048);
%input=resample(x,3840000,1920000);
cp0_len=160*sym_len/2048; cp0_len=160*sym_len/2048;
cp1_len=144*sym_len/2048; cp1_len=144*sym_len/2048;
slots=reshape(input,15360*sym_len/2048,[]); subframes=reshape(input,hflen,[]);
[n m]=size(slots); [n m]=size(subframes);
cfo=zeros(m,1); cfo=zeros(m,2);
output=zeros(size(input));
for i=1:m for i=1:m
cfo(i)=cfo_estimate(slots(:,i),7,sym_len,cp1_len,cp1_len); cfo(i,1) = cfo_estimate_cp(subframes(1:960,i),1,sym_len,cp0_len,cp1_len);
t=(i-1)*n+1:i*n; [~, cfo(i,2)] = find_pss(subframes(:,i),N_id_2);
%output(t)=input(t).*exp(-1i*2*pi*cfo(i)*t/sym_len);
end end
plot(cfo) plot(cfo)
legend('CP-based','PSS-based')

@ -1,55 +0,0 @@
function [ s0_m0 z1_m0 ] = compute_m0( m0)
%COMPUTE_S Summary of this function goes here
% Detailed explanation goes here
% Generate s_tilda
x_s_tilda(0+1) = 0;
x_s_tilda(1+1) = 0;
x_s_tilda(2+1) = 0;
x_s_tilda(3+1) = 0;
x_s_tilda(4+1) = 1;
for(i_hat=0:25)
x_s_tilda(i_hat+5+1) = mod((x_s_tilda(i_hat+2+1) + x_s_tilda(i_hat+1)), 2);
end
for(idx=0:30)
s_tilda(idx+1) = 1 - 2*x_s_tilda(idx+1);
end
% Generate c_tilda
x_c_tilda(0+1) = 0;
x_c_tilda(1+1) = 0;
x_c_tilda(2+1) = 0;
x_c_tilda(3+1) = 0;
x_c_tilda(4+1) = 1;
for(i_hat=0:25)
x_c_tilda(i_hat+5+1) = mod((x_c_tilda(i_hat+3+1) + x_c_tilda(i_hat+1)), 2);
end
for(idx=0:30)
c_tilda(idx+1) = 1 - 2*x_c_tilda(idx+1);
end
% Generate z_tilda
x_z_tilda(0+1) = 0;
x_z_tilda(1+1) = 0;
x_z_tilda(2+1) = 0;
x_z_tilda(3+1) = 0;
x_z_tilda(4+1) = 1;
for(i_hat=0:25)
x_z_tilda(i_hat+5+1) = mod((x_z_tilda(i_hat+4+1) + x_z_tilda(i_hat+2+1) + x_z_tilda(i_hat+1+1) + x_z_tilda(i_hat+1)), 2);
end
for(idx=0:30)
z_tilda(idx+1) = 1 - 2*x_z_tilda(idx+1);
end
% Generate s0_m0 and s1_m1
for(n=0:30)
s0_m0(n+1) = s_tilda(mod(n + m0, 31)+1);
end
% Generate z1_m0 and z1_m1
for(n=0:30)
z1_m0(n+1) = z_tilda(mod(n + mod(m0, 8), 31)+1);
end
end

@ -1,49 +0,0 @@
function [ s1_m1 ] = compute_m1( m1, N_id_2)
%COMPUTE_S Summary of this function goes here
% Detailed explanation goes here
% Generate s_tilda
x_s_tilda(0+1) = 0;
x_s_tilda(1+1) = 0;
x_s_tilda(2+1) = 0;
x_s_tilda(3+1) = 0;
x_s_tilda(4+1) = 1;
for(i_hat=0:25)
x_s_tilda(i_hat+5+1) = mod((x_s_tilda(i_hat+2+1) + x_s_tilda(i_hat+1)), 2);
end
for(idx=0:30)
s_tilda(idx+1) = 1 - 2*x_s_tilda(idx+1);
end
% Generate c_tilda
x_c_tilda(0+1) = 0;
x_c_tilda(1+1) = 0;
x_c_tilda(2+1) = 0;
x_c_tilda(3+1) = 0;
x_c_tilda(4+1) = 1;
for(i_hat=0:25)
x_c_tilda(i_hat+5+1) = mod((x_c_tilda(i_hat+3+1) + x_c_tilda(i_hat+1)), 2);
end
for(idx=0:30)
c_tilda(idx+1) = 1 - 2*x_c_tilda(idx+1);
end
% Generate z_tilda
x_z_tilda(0+1) = 0;
x_z_tilda(1+1) = 0;
x_z_tilda(2+1) = 0;
x_z_tilda(3+1) = 0;
x_z_tilda(4+1) = 1;
for(i_hat=0:25)
x_z_tilda(i_hat+5+1) = mod((x_z_tilda(i_hat+4+1) + x_z_tilda(i_hat+2+1) + x_z_tilda(i_hat+1+1) + x_z_tilda(i_hat+1)), 2);
end
for(idx=0:30)
z_tilda(idx+1) = 1 - 2*x_z_tilda(idx+1);
end
% Generate s0_m0 and s1_m1
for(n=0:30)
s1_m1(n+1) = s_tilda(mod(n + m1, 31)+1);
end
end

@ -1,57 +0,0 @@
function [out] = convfft(z1,z2)
%CONVFFT FFT-based convolution and polynomial multiplication.
% C = CONVFFT(A, B) convolves vectors A and B. The resulting
% vector is length LENGTH(A)+LENGTH(B)-1.
% If A and B are vectors of polynomial coefficients, convolving
% them is equivalent to multiplying the two polynomials.
%
% Please contribute if you find this software useful.
% Report bugs to luigi.rosa@tiscali.it
%
%*****************************************************************
% Luigi Rosa
% Via Centrale 27
% 67042 Civita di Bagno
% L'Aquila --- ITALY
% email luigi.rosa@tiscali.it
% mobile +39 340 3463208
% http://utenti.lycos.it/matlab
%*****************************************************************
%
z1x=size(z1,1);
z1y=size(z1,2);
z2x=size(z2,1);
z2y=size(z2,2);
if (~isa(z1,'double'))||(~isa(z2,'double'))||(ndims(z1)>2)||(ndims(z2)>2)
disp('Error: input vector must be unidimensional double array');
out=[];
return;
else
if ((z1x>1)&&(z1y>1)) || ((z2x>1)&&(z2y>1))
out=[];
disp('Error: input vectors are double matrices');
return;
else
if (z1x==1)&&(z1y>1)
z1=z1';
z1x=z1y;
end
if (z2x==1)&&(z2y>1)
z2=z2';
z2x=z2y;
end
if (any(any(imag(z1))))||(any(any(imag(z2))))
out=(ifft(fft(z1,z1x+z2x-1).*fft(z2,z1x+z2x-1)));
else
out=real(ifft(fft(z1,z1x+z2x-1).*fft(z2,z1x+z2x-1)));
end
end
end

@ -1,82 +0,0 @@
function [coarse_start freq_offset] = find_coarse_time_and_freq_offset(in, N_cp_l_else)
% Decompose input
in_re = real(in);
in_im = imag(in);
abs_corr = zeros(1,960);
for(slot=0:10)
for(n=1:40:960)
corr_re = 0;
corr_im = 0;
for(z=1:N_cp_l_else)
index = (slot*960) + n-1 + z;
corr_re = corr_re + in_re(index)*in_re(index+128) + in_im(index)*in_im(index+128);
corr_im = corr_im + in_re(index)*in_im(index+128) - in_im(index)*in_re(index+128);
end
abs_corr(n) = abs_corr(n) + corr_re*corr_re + corr_im*corr_im;
end
end
% Find first and second max
abs_corr_idx = zeros(1,2);
for(m=0:1)
abs_corr_max = 0;
for(n=1:480)
if(abs_corr((m*480)+n) > abs_corr_max)
abs_corr_max = abs_corr((m*480)+n);
abs_corr_idx(m+1) = (m*480)+n;
end
end
end
% Fine correlation and fraction frequency offset
abs_corr = zeros(1,960);
corr_freq_err = zeros(1,960);
for(slot=1:10)
for(idx=1:2)
if((abs_corr_idx(idx) - 40) < 1)
abs_corr_idx(idx) = 41;
end
if((abs_corr_idx(idx) + 40) > 960)
abs_corr_idx(idx) = 960 - 40;
end
for(n=abs_corr_idx(idx)-40:abs_corr_idx(idx)+40)
corr_re = 0;
corr_im = 0;
for(z=1:N_cp_l_else)
index = (slot*960) + n-1 + z;
corr_re = corr_re + in_re(index)*in_re(index+128) + in_im(index)*in_im(index+128);
corr_im = corr_im + in_re(index)*in_im(index+128) - in_im(index)*in_re(index+128);
end
abs_corr(n) = abs_corr(n) + corr_re*corr_re + corr_im*corr_im;
corr_freq_err(n) = corr_freq_err(n) + atan2(corr_im, corr_re)/(128*2*pi*(0.0005/960));
end
end
end
% Find first and second max
abs_corr_idx = zeros(1,2);
for(m=0:1)
abs_corr_max = 0;
for(n=1:480)
if(abs_corr((m*480)+n) > abs_corr_max)
abs_corr_max = abs_corr((m*480)+n);
abs_corr_idx(m+1) = (m*480)+n;
end
end
end
% Determine frequency offset FIXME No integer offset is calculated here
freq_offset = (corr_freq_err(abs_corr_idx(1))/10 + corr_freq_err(abs_corr_idx(2))/10)/2;23
% Determine the symbol start locations from the correlation peaks
% FIXME Needs some work
tmp = abs_corr_idx(1);
while(tmp > 0)
tmp = tmp - 2192;
end
for(n=1:7)
coarse_start(n) = tmp + (n*2192);
end
end

@ -1,31 +1,18 @@
function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot, threshold) function [ fs, cfo, p_m, w2] = find_pss( x, N_id_2)
if nargin == 2
doplot = false;
threshold = 0;
end
if nargin == 3
threshold = 0;
end
c=lte_pss_zc(N_id_2); c=lte_pss_zc(N_id_2);
cc=[zeros(33,1); c; zeros(33,1)]; cc=[zeros(33,1); c; zeros(33,1)];
ccf=[0; cc(65:128); cc(2:64)]; ccf=[0; cc(65:128); cc(2:64)];
ccf=conj(ifft(ccf)); ccf=conj(ifft(ccf));
w2=conv(x,ccf); w2=conv(x,ccf);
if (doplot) [m, fs]=max(abs(w2));
%plot(10*log10(abs(w2)));%./mean(abs(w2))));
plot(abs(w2))
%axis([0 length(w2) 0 20])
end
[m i]=max(abs(w2));
fs=i-960;
p_m = m/mean(abs(w2));
if doplot y=ccf.*x(fs-128:fs-1);
fprintf('Frame starts at %d, m=%g, p=%g, p/m=%g dB\n',fs, ... y0=y(1:64);
mean(abs(w2)), m, 10*log10(m/mean(abs(w2)))); y1=y(65:length(y));
end
cfo=angle(conj(sum(y0))*sum(y1))/pi;
p_m = m/mean(abs(w2));
end end

@ -2,18 +2,18 @@ clear
ueConfig=struct('NULRB',6,'DuplexMode','FDD','CyclicPrefix','Normal'); ueConfig=struct('NULRB',6,'DuplexMode','FDD','CyclicPrefix','Normal');
prachConfig=struct('Format',0,'SeqIdx',0,'PreambleIdx',0,'CyclicShiftIdx',0,'HighSpeed',0,'TimingOffset',0,'FreqIdx',0,'FreqOffset',0); prachConfig=struct('Format',0,'SeqIdx',0,'PreambleIdx',0,'CyclicShiftIdx',0,'HighSpeed',0,'TimingOffset',0,'FreqIdx',0,'FreqOffset',0);
addpath('../../debug/lte/phy/lib/phch/test') addpath('../../debug/srslte/lib/phch/test')
NULRB=[15 25 50 100]; NULRB=[6 15 25 50 100];
% FreqIdx, FreqOffset and TimeOffset need to be tested % FreqIdx, FreqOffset and TimeOffset need to be tested
for n_rb=1:length(NULRB) for n_rb=3:length(NULRB)
for format=1:3; for format=0;
for seqIdx=0:17:837 for seqIdx=0:17:237
fprintf('RB: %d, format %d, seqIdx: %d\n',NULRB(n_rb),format,seqIdx); fprintf('RB: %d, format %d, seqIdx: %d\n',NULRB(n_rb),format,seqIdx);
for preambleIdx=0:23:63 for preambleIdx=0:23:63
for CyclicShift=0:6:15 for CyclicShift=1:3:15
%for hs=0:1 %for hs=0:1
hs=0; hs=0;
ueConfig.NULRB=NULRB(n_rb); ueConfig.NULRB=NULRB(n_rb);
@ -22,8 +22,8 @@ for n_rb=1:length(NULRB)
prachConfig.PreambleIdx=preambleIdx; prachConfig.PreambleIdx=preambleIdx;
prachConfig.CyclicShiftIdx=CyclicShift; prachConfig.CyclicShiftIdx=CyclicShift;
prachConfig.HighSpeed=hs; prachConfig.HighSpeed=hs;
prachConfig.FreqIdx=5; prachConfig.FreqIdx=0;
prachConfig.FreqOffest=5; prachConfig.FreqOffset=0;
lib=srslte_prach(ueConfig,prachConfig); lib=srslte_prach(ueConfig,prachConfig);
[mat, info]=ltePRACH(ueConfig,prachConfig); [mat, info]=ltePRACH(ueConfig,prachConfig);

@ -51,6 +51,7 @@ class tti_sync
init_counters(0); init_counters(0);
} }
virtual void increase() = 0; virtual void increase() = 0;
virtual void resync() = 0;
virtual uint32_t wait() = 0; virtual uint32_t wait() = 0;
virtual void set_producer_cntr(uint32_t) = 0; virtual void set_producer_cntr(uint32_t) = 0;
uint32_t get_producer_cntr() { return producer_cntr; } uint32_t get_producer_cntr() { return producer_cntr; }

@ -48,6 +48,7 @@ class tti_sync_cv : public tti_sync
~tti_sync_cv(); ~tti_sync_cv();
void increase(); void increase();
uint32_t wait(); uint32_t wait();
void resync();
void set_producer_cntr(uint32_t producer_cntr); void set_producer_cntr(uint32_t producer_cntr);
private: private:

@ -56,6 +56,11 @@ namespace srslte {
return x; return x;
} }
void tti_sync_cv::resync()
{
consumer_cntr = producer_cntr;
}
void tti_sync_cv::set_producer_cntr(uint32_t producer_cntr) void tti_sync_cv::set_producer_cntr(uint32_t producer_cntr)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);

@ -32,7 +32,7 @@
#include "srsapps/ue/mac/mac_io.h" #include "srsapps/ue/mac/mac_io.h"
#include "srsapps/common/timers.h" #include "srsapps/common/timers.h"
#include "srsapps/ue/mac/mac_params.h" #include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac_pdu.h" #include "srsapps/ue/mac/pdu.h"
#ifndef DEMUX_H #ifndef DEMUX_H
#define DEMUX_H #define DEMUX_H
@ -57,11 +57,11 @@ public:
uint64_t get_contention_resolution_id(); uint64_t get_contention_resolution_id();
private: private:
mac_pdu mac_msg; sch_pdu mac_msg;
mac_pdu pending_mac_msg; sch_pdu pending_mac_msg;
void process_pdu(mac_pdu *pdu); void process_pdu(sch_pdu *pdu);
bool process_ce(mac_pdu::mac_subh *subheader); bool process_ce(sch_subh *subheader);
uint64_t contention_resolution_id; uint64_t contention_resolution_id;
bool pending_temp_rnti; bool pending_temp_rnti;

@ -75,6 +75,7 @@ private:
uint32_t pid; uint32_t pid;
private: private:
bool is_initiated;
dl_harq_entity *harq_entity; dl_harq_entity *harq_entity;
uint8_t *payload; uint8_t *payload;
uint32_t max_payload_len; uint32_t max_payload_len;
@ -89,7 +90,6 @@ private:
srslte_softbuffer_rx_t softbuffer; srslte_softbuffer_rx_t softbuffer;
}; };
dl_harq_process *proc; dl_harq_process *proc;
timers *timers_db; timers *timers_db;
demux *demux_unit; demux *demux_unit;

@ -1,165 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/common/log.h"
#ifndef MACPDU_H
#define MACPDU_H
/* MAC PDU Packing/Unpacking functions */
namespace srslte {
namespace ue {
class mac_pdu
{
public:
class mac_subh
{
public:
typedef enum {
C_RNTI = 0,
CON_RES_ID,
TA_CMD,
PHD,
SDU
} cetype;
// Reading functions
bool is_sdu();
cetype ce_type();
uint32_t get_sdu_lcid();
uint32_t get_sdu_nbytes();
uint8_t* get_sdu_ptr();
uint16_t get_c_rnti();
uint64_t get_con_res_id();
uint8_t get_ta_cmd();
uint8_t get_phd();
// Writing functions
bool set_sdu(uint8_t *ptr, uint32_t nof_bytes);
bool set_c_rnti(uint16_t crnti);
bool set_con_res_id(uint64_t con_res_id);
bool set_ta_cmd(uint8_t ta_cmd);
bool set_phd(uint8_t phd);
private:
static const int MAX_CE_PAYLOAD_LEN = 8;
uint32_t lcid;
uint32_t nof_bytes;
uint8_t* sdu_payload_ptr;
uint8_t ce_payload[MAX_CE_PAYLOAD_LEN];
};
mac_pdu(uint32_t max_subheaders);
void reset();
void init(uint32_t pdu_len);
bool read_next();
bool write_next();
mac_subh* get();
bool write_packet(uint8_t *ptr);
void parse_packet(uint8_t *ptr);
protected:
mac_subh *subheaders;
uint32_t pdu_len;
uint32_t rem_len;
uint32_t rp, wp;
uint32_t nof_subheaders;
uint32_t max_subheaders;
};
class mac_rar_pdu
{
public:
class mac_rar
{
public:
static const uint32_t RAR_GRANT_LEN = 20;
// Reading functions
uint32_t get_rapid();
uint32_t get_ta_cmd();
uint16_t get_temp_crnti();
void get_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
// Writing functoins
void set_rapid(uint32_t rapid);
void set_ta_cmd(uint32_t ta);
void set_temp_crnti(uint16_t temp_rnti);
void set_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
private:
uint8_t grant[RAR_GRANT_LEN];
uint32_t ta;
uint16_t temp_rnti;
};
mac_rar_pdu(uint32_t max_rars);
void reset();
void init(uint32_t pdu_len);
bool read_next();
bool write_next();
mac_rar* get();
void set_backoff(uint8_t bi);
bool is_backoff();
uint8_t get_backoff();
bool write_packet(uint8_t *ptr);
void parse_packet(uint8_t *ptr);
private:
mac_rar *rars;
uint32_t pdu_len;
uint32_t rem_len;
uint32_t rp, wp;
uint32_t nof_rars;
uint32_t max_rars;
};
}
}
#endif

@ -31,7 +31,7 @@
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_io.h" #include "srsapps/ue/mac/mac_io.h"
#include "srsapps/ue/mac/mac_params.h" #include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac_pdu.h" #include "srsapps/ue/mac/pdu.h"
#ifndef MUX_H #ifndef MUX_H
#define MUX_H #define MUX_H
@ -48,6 +48,8 @@ public:
void reset(); void reset();
void init(log *log_h, mac_io *mac_io_h); void init(log *log_h, mac_io *mac_io_h);
bool is_pending_sdu();
uint8_t* pdu_pop(uint32_t tti_, uint32_t pdu_sz); uint8_t* pdu_pop(uint32_t tti_, uint32_t pdu_sz);
bool pdu_move_to_msg3(uint32_t tti, uint32_t pdu_sz); bool pdu_move_to_msg3(uint32_t tti, uint32_t pdu_sz);
void pdu_release(); void pdu_release();
@ -63,8 +65,8 @@ public:
private: private:
bool assemble_pdu(uint32_t pdu_sz); bool assemble_pdu(uint32_t pdu_sz);
bool allocate_sdu(uint32_t lcid, mac_pdu *pdu, uint32_t *sdu_sz); bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, uint32_t *sdu_sz);
bool allocate_sdu(uint32_t lcid, mac_pdu *pdu); bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
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
@ -89,7 +91,7 @@ private:
/* PDU Buffer */ /* PDU Buffer */
static const uint32_t PDU_BUFF_SZ = 16*1024; static const uint32_t PDU_BUFF_SZ = 16*1024;
qbuff pdu_buff; qbuff pdu_buff;
mac_pdu pdu_msg; sch_pdu pdu_msg;
}; };
} }

@ -0,0 +1,285 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/common/log.h"
#include <vector>
#include <stdio.h>
#ifndef MACPDU_H
#define MACPDU_H
/* MAC PDU Packing/Unpacking functions. Section 6 of 36.321 */
namespace srslte {
namespace ue {
template<class SubH>
class pdu
{
public:
pdu(uint32_t max_subheaders_) : subheaders(max_subheaders_) {
max_subheaders = max_subheaders_;
nof_subheaders = 0;
cur_idx = -1;
pdu_len = 0;
rem_len = 0;
for (int i=0;i<max_subheaders;i++) {
subheaders[i].parent = this;
}
}
void fprint(FILE *stream) {
fprintf(stream, "Number of Subheaders: %d\n", nof_subheaders);
for (int i=0;i<nof_subheaders;i++) {
fprintf(stream, " -- Subheader %d: ", i);
subheaders[i].fprint(stream);
}
}
/* Resets the Read/Write position and remaining PDU length */
void reset() {
cur_idx = -1;
rem_len = pdu_len;
}
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */
void init(uint32_t pdu_len_bytes) {
init(pdu_len_bytes, false);
}
void init(uint32_t pdu_len_bytes, bool is_ulsch) {
nof_subheaders = 0;
pdu_len = pdu_len_bytes;
rem_len = pdu_len;
pdu_is_ul = is_ulsch;
reset();
for (int i=0;i<max_subheaders;i++) {
subheaders[i].init();
}
}
bool new_subh() {
if (nof_subheaders < max_subheaders - 1) {
nof_subheaders++;
return true;
} else {
return false;
}
}
bool next() {
if (cur_idx < nof_subheaders - 1) {
cur_idx++;
return true;
} else {
return false;
}
}
SubH* get() {
if (cur_idx >= 0) {
return &subheaders[cur_idx];
}
}
// Section 6.1.2
void parse_packet(uint8_t *ptr) {
nof_subheaders = 0;
while(subheaders[nof_subheaders].read_subheader(&ptr)) {
nof_subheaders++;
}
nof_subheaders++;
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].read_payload(&ptr);
}
}
bool is_ul() {
return pdu_is_ul;
}
virtual bool write_packet(uint8_t *ptr) = 0;
protected:
std::vector<SubH> subheaders;
uint32_t pdu_len;
uint32_t rem_len;
int cur_idx;
int nof_subheaders;
uint32_t max_subheaders;
bool pdu_is_ul;
};
template<class SubH>
class subh
{
public:
virtual bool read_subheader(uint8_t** ptr) = 0;
virtual void read_payload(uint8_t **ptr) = 0;
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
virtual void write_payload(uint8_t **ptr) = 0;
virtual void fprint(FILE *stream) = 0;
pdu<SubH>* parent;
private:
virtual void init() = 0;
};
class sch_subh : public subh<sch_subh>
{
public:
typedef enum {
PHD_REPORT = 26,
C_RNTI = 27,
CON_RES_ID = 28,
TRUNC_BSR = 28,
TA_CMD = 29,
SHORT_BSR = 29,
DRX_CMD = 30,
LONG_BSR = 30,
PADDING = 31,
SDU = 0
} cetype;
// Reading functions
bool is_sdu();
cetype ce_type();
bool read_subheader(uint8_t** ptr);
void read_payload(uint8_t **ptr);
uint32_t get_sdu_lcid();
uint32_t get_sdu_nbytes();
uint8_t* get_sdu_ptr();
uint16_t get_c_rnti();
uint64_t get_con_res_id();
uint8_t get_ta_cmd();
uint8_t get_phd();
// Writing functions
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t **ptr);
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes);
bool set_c_rnti(uint16_t crnti);
bool set_con_res_id(uint64_t con_res_id);
bool set_ta_cmd(uint8_t ta_cmd);
bool set_phd(uint8_t phd);
void set_padding();
void init();
void fprint(FILE *stream);
private:
static const int MAX_CE_PAYLOAD_LEN = 8;
uint32_t lcid;
uint32_t nof_bytes;
uint8_t* sdu_payload_ptr;
bool F_bit;
uint8_t ce_payload[MAX_CE_PAYLOAD_LEN];
uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
};
class sch_pdu : public pdu<sch_subh>
{
public:
sch_pdu(uint32_t max_rars) : pdu(max_rars) {}
bool write_packet(uint8_t *ptr);
bool has_space_ce(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes);
static uint32_t size_plus_header_pdu(uint32_t nbytes);
bool update_space_ce(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes);
void fprint(FILE *stream);
};
class rar_subh : public subh<rar_subh>
{
public:
static const uint32_t RAR_GRANT_LEN = 20;
// Reading functions
bool read_subheader(uint8_t** ptr);
void read_payload(uint8_t** ptr);
uint32_t get_rapid();
uint32_t get_ta_cmd();
uint16_t get_temp_crnti();
void get_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
// Writing functoins
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t** ptr);
void set_rapid(uint32_t rapid);
void set_ta_cmd(uint32_t ta);
void set_temp_crnti(uint16_t temp_rnti);
void set_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
void init();
void fprint(FILE *stream);
private:
uint8_t grant[RAR_GRANT_LEN];
uint32_t ta;
uint16_t temp_rnti;
uint32_t preamble;
};
class rar_pdu : public pdu<rar_subh>
{
public:
rar_pdu(uint32_t max_rars);
void set_backoff(uint8_t bi);
bool has_backoff();
uint8_t get_backoff();
bool write_packet(uint8_t* ptr);
void fprint(FILE *stream);
private:
bool has_backoff_indicator;
uint8_t backoff_indicator;
};
}
}
#endif

@ -37,7 +37,7 @@
#include "srsapps/common/timers.h" #include "srsapps/common/timers.h"
#include "srsapps/ue/mac/mux.h" #include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/demux.h" #include "srsapps/ue/mac/demux.h"
#include "srsapps/ue/mac/mac_pdu.h" #include "srsapps/ue/mac/pdu.h"
#ifndef PROCRA_H #ifndef PROCRA_H
#define PROCRA_H #define PROCRA_H
@ -50,7 +50,7 @@ namespace ue {
class ra_proc : public proc,timer_callback class ra_proc : public proc,timer_callback
{ {
public: public:
ra_proc() : rar_pdu(20) {}; ra_proc() : rar_pdu_msg(20) {};
bool init(mac_params *params_db, phy *phy_h, log *log_h, timers *timers_db, bool init(mac_params *params_db, phy *phy_h, log *log_h, timers *timers_db,
mux *mux_unit, demux *demux_unit); mux *mux_unit, demux *demux_unit);
void reset(); void reset();
@ -64,10 +64,12 @@ class ra_proc : public proc,timer_callback
bool in_progress(); bool in_progress();
void pdcch_to_crnti(bool is_ul_grant); void pdcch_to_crnti(bool is_ul_grant);
void timer_expired(uint32_t timer_id); void timer_expired(uint32_t timer_id);
private: private:
void process_timeadv_cmd(uint32_t tti, uint32_t ta_cmd); void process_timeadv_cmd(uint32_t tti, uint32_t ta_cmd);
void step_initialization(); void step_initialization();
void step_initialization_wait();
void step_resource_selection(); void step_resource_selection();
void step_preamble_transmission(); void step_preamble_transmission();
void step_response_reception(); void step_response_reception();
@ -79,7 +81,7 @@ private:
// Buffer to receive RAR PDU // Buffer to receive RAR PDU
static const uint32_t MAX_RAR_PDU_LEN = 2048; static const uint32_t MAX_RAR_PDU_LEN = 2048;
uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN]; uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN];
mac_rar_pdu rar_pdu; rar_pdu rar_pdu_msg;
// Random Access parameters provided by higher layers defined in 5.1.1 // Random Access parameters provided by higher layers defined in 5.1.1
// They are read from params_db during initialization init() // They are read from params_db during initialization init()
@ -116,6 +118,7 @@ private:
enum { enum {
IDLE = 0, IDLE = 0,
INITIALIZATION, // Section 5.1.1 INITIALIZATION, // Section 5.1.1
INITIALIZATION_WAIT,
RESOURCE_SELECTION, // Section 5.1.2 RESOURCE_SELECTION, // Section 5.1.2
PREAMBLE_TRANSMISSION, // Section 5.1.3 PREAMBLE_TRANSMISSION, // Section 5.1.3
RESPONSE_RECEPTION, // Section 5.1.4 RESPONSE_RECEPTION, // Section 5.1.4
@ -140,6 +143,8 @@ private:
mux *mux_unit; mux *mux_unit;
demux *demux_unit; demux *demux_unit;
pthread_t pt_init_prach;
uint64_t received_contention_id; uint64_t received_contention_id;
uint64_t transmitted_contention_id; uint64_t transmitted_contention_id;
uint16_t transmitted_crnti; uint16_t transmitted_crnti;

@ -54,14 +54,14 @@ public:
ul_harq_entity(); ul_harq_entity();
~ul_harq_entity(); ~ul_harq_entity();
bool init(srslte_cell_t cell, uint32_t max_payload_len, log *log_h, timers* timers_, mux *mux_unit); bool init(srslte_cell_t cell, log *log_h, timers* timers_, mux *mux_unit);
void set_maxHARQ_Tx(uint32_t maxHARQ_Tx, uint32_t maxHARQ_Msg3Tx); void set_maxHARQ_Tx(uint32_t maxHARQ_Tx, uint32_t maxHARQ_Msg3Tx);
void reset(); void reset();
void reset_ndi(); void reset_ndi();
bool is_sps(uint32_t pid); bool is_sps(uint32_t pid);
void run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_); void run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_);
void run_tti(uint32_t tti, phy *phy_); void run_tti(uint32_t tti, dl_buffer *dl_buffer, phy *phy_);
bool is_last_retx_msg3(); bool is_last_retx_msg3();
private: private:
@ -69,7 +69,7 @@ private:
class ul_harq_process { class ul_harq_process {
public: public:
ul_harq_process(); ul_harq_process();
bool init(srslte_cell_t cell, uint32_t max_payload_len, ul_harq_entity *parent); bool init(srslte_cell_t cell, ul_harq_entity *parent);
void reset(); void reset();
void reset_ndi(); void reset_ndi();
void set_maxHARQ_Tx(uint32_t maxHARQ_Tx_, uint32_t maxHARQ_Msg3Tx_); void set_maxHARQ_Tx(uint32_t maxHARQ_Tx_, uint32_t maxHARQ_Msg3Tx_);
@ -83,6 +83,7 @@ private:
void set_harq_feedback(bool ack); void set_harq_feedback(bool ack);
bool get_ndi(); bool get_ndi();
uint32_t tti;
private: private:
uint32_t current_tx_nb; uint32_t current_tx_nb;
uint32_t current_irv; uint32_t current_irv;
@ -91,14 +92,13 @@ private:
srslte::log *log_h; srslte::log *log_h;
ul_harq_entity *harq_entity; ul_harq_entity *harq_entity;
ul_sched_grant cur_grant; ul_sched_grant cur_grant;
uint8_t *payload;
uint32_t max_payload_len;
bool is_grant_configured; bool is_grant_configured;
srslte_softbuffer_tx_t softbuffer; srslte_softbuffer_tx_t softbuffer;
uint32_t maxHARQ_Tx, maxHARQ_Msg3Tx; uint32_t maxHARQ_Tx, maxHARQ_Msg3Tx;
bool is_msg3; bool is_msg3;
bool is_initiated;
void generate_tx(ul_buffer* ul); void generate_tx(uint8_t *pdu_payload, ul_buffer* ul);
}; };
bool last_retx_is_msg3; bool last_retx_is_msg3;

@ -81,13 +81,16 @@ void demux::push_pdu_temp_crnti(uint32_t tti_, uint8_t *mac_pdu, uint32_t nof_bi
tti = tti_; tti = tti_;
if (!pending_temp_rnti) { if (!pending_temp_rnti) {
// Unpack DLSCH MAC PDU // Unpack DLSCH MAC PDU
pending_mac_msg.init(nof_bits); 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);
//MIRAR ACK PENDING. EL QUE PASSA ES QUE AL HARQ NO FA RES SI EL CONTENTION RES ID ES 0, PERQUE ES 0???
// Look for Contention Resolution UE ID // Look for Contention Resolution UE ID
contention_resolution_id = 0; contention_resolution_id = 0;
while(pending_mac_msg.read_next()) { while(pending_mac_msg.next()) {
if (pending_mac_msg.get()->ce_type() == mac_pdu::mac_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();
} }
} }
@ -103,7 +106,7 @@ void demux::push_pdu(uint32_t tti_, uint8_t *mac_pdu, uint32_t nof_bits)
{ {
tti = tti_; tti = tti_;
// Unpack DLSCH MAC PDU // Unpack DLSCH MAC PDU
mac_msg.init(nof_bits); mac_msg.init(nof_bits/8);
mac_msg.parse_packet(mac_pdu); mac_msg.parse_packet(mac_pdu);
process_pdu(&mac_msg); process_pdu(&mac_msg);
Debug("Normal MAC PDU processed\n"); Debug("Normal MAC PDU processed\n");
@ -124,26 +127,26 @@ void demux::demultiplex_pending_pdu(uint32_t tti_)
void demux::process_pdu(mac_pdu *pdu) void demux::process_pdu(sch_pdu *pdu_msg)
{ {
while(pdu->read_next()) { while(pdu_msg->next()) {
if (pdu->get()->is_sdu()) { if (pdu_msg->get()->is_sdu()) {
// Route logical channel // Route logical channel
if (pdu->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) { if (pdu_msg->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) {
qbuff *dest_lch = mac_io_h->get(pdu->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->get()->get_sdu_ptr(), pdu->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", Debug("Sent MAC SDU len=%d bytes to lchid=%d\n",
pdu->get()->get_sdu_nbytes(), pdu->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->get()->get_sdu_lcid()); Error("Getting destination channel LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
} }
} else { } else {
Warning("Received SDU for unsupported LCID=%d\n", pdu->get()->get_sdu_lcid()); Warning("Received SDU for unsupported LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
} }
// Process MAC Control Element // Process MAC Control Element
} else { } else {
if (!process_ce(pdu->get())) { if (!process_ce(pdu_msg->get())) {
Warning("Received Subheader with invalid or unkonwn LCID\n"); Warning("Received Subheader with invalid or unkonwn LCID\n");
} }
} }
@ -151,13 +154,13 @@ void demux::process_pdu(mac_pdu *pdu)
} }
bool demux::process_ce(mac_pdu::mac_subh *subh) { bool demux::process_ce(sch_subh *subh) {
switch(subh->ce_type()) { switch(subh->ce_type()) {
case mac_pdu::mac_subh::CON_RES_ID: case sch_subh::CON_RES_ID:
contention_resolution_id = subh->get_c_rnti(); contention_resolution_id = subh->get_c_rnti();
Debug("Saved Contention Resolution ID=%d\n", contention_resolution_id); Debug("Saved Contention Resolution ID=%d\n", contention_resolution_id);
break; break;
case mac_pdu::mac_subh::TA_CMD: case sch_subh::TA_CMD:
phy_h->set_timeadv(subh->get_ta_cmd()); phy_h->set_timeadv(subh->get_ta_cmd());
// Start or restart timeAlignmentTimer // Start or restart timeAlignmentTimer

@ -109,6 +109,7 @@ void dl_harq_entity::send_pending_ack_contention_resolution()
dl_harq_entity::dl_harq_process::dl_harq_process() : cur_grant(0),pending_ack_grant(0) { dl_harq_entity::dl_harq_process::dl_harq_process() : cur_grant(0),pending_ack_grant(0) {
is_first_tx = true; is_first_tx = true;
is_first_decoded = true; is_first_decoded = true;
is_initiated = false;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant)); bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
payload = NULL; payload = NULL;
max_payload_len = 0; max_payload_len = 0;
@ -118,7 +119,9 @@ void dl_harq_entity::dl_harq_process::reset() {
is_first_tx = true; is_first_tx = true;
is_first_decoded = true; is_first_decoded = true;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant)); bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
if (is_initiated) {
srslte_softbuffer_rx_reset(&softbuffer); srslte_softbuffer_rx_reset(&softbuffer);
}
} }
void dl_harq_entity::dl_harq_process::send_pending_ack_contention_resolution() void dl_harq_entity::dl_harq_process::send_pending_ack_contention_resolution()
@ -169,6 +172,7 @@ void dl_harq_entity::dl_harq_process::receive_data(uint32_t tti, srslte::ue::dl_
pending_ul_buffer = phy_h->get_ul_buffer(tti+4); pending_ul_buffer = phy_h->get_ul_buffer(tti+4);
harq_entity->pending_ack_pid = pid; harq_entity->pending_ack_pid = pid;
memcpy(&pending_ack_grant, &cur_grant, sizeof(dl_sched_grant)); memcpy(&pending_ack_grant, &cur_grant, sizeof(dl_sched_grant));
Debug("ACK pending contention resolution\n");
} else { } else {
Debug("Generating ACK\n"); Debug("Generating ACK\n");
// Generate ACK // Generate ACK
@ -209,6 +213,7 @@ bool dl_harq_entity::dl_harq_process::init(srslte_cell_t cell, uint32_t max_payl
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
return false; return false;
} else { } else {
is_initiated = true;
harq_entity = parent; harq_entity = parent;
log_h = harq_entity->log_h; log_h = harq_entity->log_h;
payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len); payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len);

@ -53,7 +53,14 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
reset(); reset();
if (!pthread_create(&mac_thread, NULL, mac_thread_fnc, this)) { pthread_attr_t attr;
struct sched_param param;
param.sched_priority = -20;
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 { } else {
perror("pthread_create"); perror("pthread_create");
@ -64,7 +71,6 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
void mac::stop() void mac::stop()
{ {
started = false; started = false;
pthread_join(mac_thread, NULL); pthread_join(mac_thread, NULL);
} }
@ -126,7 +132,7 @@ void mac::main_radio_loop() {
// Init HARQ for this cell // Init HARQ for this cell
Info("Init UL/DL HARQ\n"); Info("Init UL/DL HARQ\n");
ul_harq.init(cell, 8*1024, log_h, &timers_db, &mux_unit); ul_harq.init(cell, log_h, &timers_db, &mux_unit);
dl_harq.init(cell, 8*1024, log_h, &timers_db, &demux_unit); dl_harq.init(cell, 8*1024, log_h, &timers_db, &demux_unit);
// Set the current PHY cell to the detected cell // Set the current PHY cell to the detected cell
@ -134,12 +140,16 @@ void mac::main_radio_loop() {
if (phy_h->set_cell(cell)) { if (phy_h->set_cell(cell)) {
Info("Starting RX streaming\n"); Info("Starting RX streaming\n");
if (phy_h->start_rxtx()) { if (phy_h->start_rxtx()) {
tti = ttisync->wait();
Info("Receiver synchronized\n"); Info("Receiver synchronized\n");
// Send MIB to RRC // Send MIB to RRC
mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->send(bch_payload, SRSLTE_BCH_PAYLOAD_LEN); mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->send(bch_payload, SRSLTE_BCH_PAYLOAD_LEN);
ttisync->resync();
Info("Wait to sync\n");
for (int i=0;i<1000;i++) {
tti = ttisync->wait();
}
is_synchronized = true; is_synchronized = true;
} else { } else {
Error("Starting PHY receiver\n"); Error("Starting PHY receiver\n");
@ -151,9 +161,9 @@ void mac::main_radio_loop() {
} }
} else { } else {
Warning("Cell not found\n"); Warning("Cell not found\n");
}
sleep(1); sleep(1);
} }
}
if (is_synchronized) { if (is_synchronized) {
/* Warning: Here order of invocation of procedures is important!! */ /* Warning: Here order of invocation of procedures is important!! */
@ -181,10 +191,18 @@ void mac::main_radio_loop() {
// Process UL grants if RA procedure is done or in contention resolution // Process UL grants if RA procedure is done or in contention resolution
if (ra_procedure.is_successful() || ra_procedure.is_contention_resolution()) { if (ra_procedure.is_successful() || ra_procedure.is_contention_resolution()) {
Info("Processing UL grants\n");
process_ul_grants(tti); process_ul_grants(tti);
} }
timers_db.step_all(); timers_db.step_all();
// Check if there is pending CCCH SDU in Multiplexing Unit
if (mux_unit.is_pending_sdu()) {
// Start RA procedure
if (!ra_procedure.in_progress() && !ra_procedure.is_successful()) {
Info("Starting RA procedure by RLC order\n");
ra_procedure.start_rlc_order();
}
}
} }
} }
} }
@ -267,7 +285,6 @@ void mac::process_dl_grants(uint32_t tti) {
for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_RA;i++) { for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_RA;i++) {
// Check C-RNTI, SPS-RNTI and Temporal RNTI // Check C-RNTI, SPS-RNTI and Temporal RNTI
if (params_db.get_param(i) != 0) { if (params_db.get_param(i) != 0) {
Info("Searching DL grants for RNTI: %d\n", params_db.get_param(i));
dl_sched_grant ue_grant(rnti_type(i), params_db.get_param(i)); dl_sched_grant ue_grant(rnti_type(i), params_db.get_param(i));
if (dl_buffer->get_dl_grant(&ue_grant)) { if (dl_buffer->get_dl_grant(&ue_grant)) {
// If PDCCH for C-RNTI and RA procedure in Contention Resolution, notify it // If PDCCH for C-RNTI and RA procedure in Contention Resolution, notify it
@ -362,12 +379,16 @@ void mac::process_ul_grants(uint32_t tti) {
if (params_db.get_param(i) != 0) { if (params_db.get_param(i) != 0) {
ul_sched_grant ul_grant(rnti_type(i), params_db.get_param(i)); ul_sched_grant ul_grant(rnti_type(i), params_db.get_param(i));
if (dl_buffer->get_ul_grant(&ul_grant)) { if (dl_buffer->get_ul_grant(&ul_grant)) {
if (ul_grant.is_from_rar()) {
dl_buffer->release_pending_rar_grant();
}
if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) { if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) {
ra_procedure.pdcch_to_crnti(true); ra_procedure.pdcch_to_crnti(true);
} }
if (i == mac_params::RNTI_C || i == mac_params::RNTI_TEMP || ra_procedure.is_running()) { if (i == mac_params::RNTI_C || i == mac_params::RNTI_TEMP || ra_procedure.is_running()) {
if (i == mac_params::RNTI_C && ul_harq.is_sps(tti)) if (i == mac_params::RNTI_C && ul_harq.is_sps(tti)) {
ul_grant.set_ndi(true); ul_grant.set_ndi(true);
}
ul_harq.run_tti(tti, &ul_grant, phy_h); ul_harq.run_tti(tti, &ul_grant, phy_h);
if (i == mac_params::RNTI_TEMP) { if (i == mac_params::RNTI_TEMP) {
// Discard already processed RAR grant // Discard already processed RAR grant
@ -401,7 +422,7 @@ void mac::process_ul_grants(uint32_t tti) {
return; return;
} }
} }
ul_harq.run_tti(tti, phy_h); ul_harq.run_tti(tti, dl_buffer, phy_h);
} }

@ -1,214 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/mac/mac_pdu.h"
namespace srslte {
namespace ue {
mac_pdu::mac_subh* mac_pdu::get()
{
}
void mac_pdu::init(uint32_t pdu_len)
{
}
mac_pdu::mac_pdu(uint32_t max_subheaders)
{
}
mac_pdu::mac_subh::cetype mac_pdu::mac_subh::ce_type()
{
}
uint16_t mac_pdu::mac_subh::get_c_rnti()
{
}
uint64_t mac_pdu::mac_subh::get_con_res_id()
{
}
uint8_t mac_pdu::mac_subh::get_phd()
{
}
uint32_t mac_pdu::mac_subh::get_sdu_lcid()
{
}
uint32_t mac_pdu::mac_subh::get_sdu_nbytes()
{
}
uint8_t* mac_pdu::mac_subh::get_sdu_ptr()
{
}
uint8_t mac_pdu::mac_subh::get_ta_cmd()
{
}
bool mac_pdu::mac_subh::is_sdu()
{
}
bool mac_pdu::mac_subh::set_c_rnti(uint16_t crnti)
{
}
bool mac_pdu::mac_subh::set_con_res_id(uint64_t con_res_id)
{
}
bool mac_pdu::mac_subh::set_phd(uint8_t phd)
{
}
bool mac_pdu::mac_subh::set_sdu(uint8_t* ptr, uint32_t nof_bytes)
{
}
bool mac_pdu::mac_subh::set_ta_cmd(uint8_t ta_cmd)
{
}
void mac_pdu::parse_packet(uint8_t* ptr)
{
}
bool mac_pdu::read_next()
{
}
void mac_pdu::reset()
{
}
bool mac_pdu::write_next()
{
}
bool mac_pdu::write_packet(uint8_t* ptr)
{
}
mac_rar_pdu::mac_rar* mac_rar_pdu::get()
{
}
uint8_t mac_rar_pdu::get_backoff()
{
}
void mac_rar_pdu::init(uint32_t pdu_len)
{
}
bool mac_rar_pdu::is_backoff()
{
}
uint32_t mac_rar_pdu::mac_rar::get_rapid()
{
}
void mac_rar_pdu::mac_rar::get_sched_grant(uint8_t grant[])
{
}
uint32_t mac_rar_pdu::mac_rar::get_ta_cmd()
{
}
uint16_t mac_rar_pdu::mac_rar::get_temp_crnti()
{
}
void mac_rar_pdu::mac_rar::set_rapid(uint32_t rapid)
{
}
void mac_rar_pdu::mac_rar::set_sched_grant(uint8_t grant[])
{
}
void mac_rar_pdu::mac_rar::set_ta_cmd(uint32_t ta)
{
}
void mac_rar_pdu::mac_rar::set_temp_crnti(uint16_t temp_rnti)
{
}
mac_rar_pdu::mac_rar_pdu(uint32_t max_rars)
{
}
void mac_rar_pdu::parse_packet(uint8_t* ptr)
{
}
bool mac_rar_pdu::read_next()
{
}
void mac_rar_pdu::reset()
{
}
void mac_rar_pdu::set_backoff(uint8_t bi)
{
}
bool mac_rar_pdu::write_next()
{
}
bool mac_rar_pdu::write_packet(uint8_t* ptr)
{
}
}
}
#ifdef kk
bool demux::lcid_is_lch(uint32_t lcid) {
if (lcid <= LIBLTE_MAC_DLSCH_DCCH_LCID_END) {
return true;
} else {
return false;
}
}
#endif

@ -64,6 +64,11 @@ void mux::reset()
} }
} }
bool mux::is_pending_sdu()
{
return !mac_io_h->get(mac_io::MAC_LCH_CCCH_UL)->isempty();
}
void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD) void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
@ -145,7 +150,7 @@ void mux::append_crnti_ce_next_tx(uint16_t crnti) {
pending_crnti_ce = crnti; pending_crnti_ce = crnti;
} }
bool mux::assemble_pdu(uint32_t pdu_sz) { bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
uint8_t *buff = (uint8_t*) pdu_buff.request(); uint8_t *buff = (uint8_t*) pdu_buff.request();
if (!buff) { if (!buff) {
@ -154,13 +159,13 @@ bool mux::assemble_pdu(uint32_t pdu_sz) {
} }
// Make sure pdu_sz is byte-aligned // Make sure pdu_sz is byte-aligned
pdu_sz = 8*(pdu_sz/8); pdu_sz_nbits = 8*(pdu_sz_nbits/8);
// Acquire mutex. Cannot change priorities, PBR or BSD after assemble finishes // Acquire mutex. Cannot change priorities, PBR or BSD after assemble finishes
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
// Update Bj // Update Bj
for (int i=0;i=mac_io::NOF_UL_LCH;i++) { for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
// Add PRB unless it's infinity // Add PRB unless it's infinity
if (PBR[i] >= 0) { if (PBR[i] >= 0) {
Bj[i] += PBR[i]; Bj[i] += PBR[i];
@ -174,12 +179,13 @@ bool mux::assemble_pdu(uint32_t pdu_sz) {
uint32_t sdu_sz = 0; uint32_t sdu_sz = 0;
pdu_msg.init(pdu_sz); 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)) { if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg)) {
if (pending_crnti_ce) { if (pending_crnti_ce) {
if (pdu_msg.write_next()) { if (pdu_msg.new_subh()) {
pdu_msg.next();
if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) { if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) {
Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n"); Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n");
} }
@ -225,7 +231,7 @@ bool mux::assemble_pdu(uint32_t pdu_sz) {
/* 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); pdu_buff.push(pdu_sz_nbits);
} else { } else {
Error("Writing PDU message to packet\n"); Error("Writing PDU message to packet\n");
return false; return false;
@ -234,21 +240,22 @@ bool mux::assemble_pdu(uint32_t pdu_sz) {
} }
bool mux::allocate_sdu(uint32_t lcid, mac_pdu *pdu) bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg)
{ {
return allocate_sdu(lcid, pdu, NULL); return allocate_sdu(lcid, pdu_msg, NULL);
} }
bool mux::allocate_sdu(uint32_t lcid, mac_pdu *pdu, uint32_t *sdu_sz) bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz)
{ {
// 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(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) { // there is pending SDU to allocate
if (pdu->write_next()) { // there is space for a new subheader if (pdu_msg->new_subh()) { // there is space for a new subheader
if (pdu->get()->set_sdu(buff_ptr, buff_len)) { // new SDU could be added pdu_msg->next();
if (pdu_msg->get()->set_sdu(lcid, buff_ptr, buff_len/8)) { // new SDU could be added
// 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;

@ -0,0 +1,497 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include "srsapps/ue/mac/pdu.h"
#include "srslte/srslte.h"
namespace srslte {
namespace ue {
void sch_pdu::fprint(FILE* stream)
{
fprintf(stream, "MAC SDU for UL/DL-SCH. ");
pdu::fprint(stream);
}
void sch_subh::fprint(FILE* stream)
{
if (is_sdu()) {
fprintf(stream, "SDU LCHID=%d, SDU nof_bytes=%d\n", lcid, nof_bytes);
} else {
switch(lcid) {
case C_RNTI:
fprintf(stream, "C-RNTI CE: %d\n", get_c_rnti());
break;
case CON_RES_ID:
fprintf(stream, "Contention Resolution ID CE: %d\n", get_con_res_id());
break;
case TA_CMD:
fprintf(stream, "Time Advance Command CE: %d\n", get_ta_cmd());
break;
}
}
}
// Section 6.1.2
bool sch_pdu::write_packet(uint8_t* ptr)
{
// Add single or two-byte padding if required
if (rem_len == 1 || rem_len == 2) {
sch_subh padding;
padding.set_padding();
for (int i=0;i<rem_len;i++) {
padding.write_subheader(&ptr, false);
}
rem_len = 0;
}
// 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--;
}
int last_sh = subheaders[last_sdu].is_sdu()?last_sdu:last_ce;
// Write subheaders for MAC CE first
for (int i=0;i<nof_subheaders;i++) {
if (!subheaders[i].is_sdu()) {
subheaders[i].write_subheader(&ptr, i==last_sh);
}
}
// Then for SDUs
for (int i=0;i<nof_subheaders;i++) {
if (subheaders[i].is_sdu()) {
subheaders[i].write_subheader(&ptr, i==last_sh);
}
}
// Write payloads in the same order
for (int i=0;i<nof_subheaders;i++) {
if (!subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr);
}
}
for (int i=0;i<nof_subheaders;i++) {
if (subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr);
}
}
// Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8);
}
uint32_t sch_pdu::size_plus_header_pdu(uint32_t nbytes)
{
if (nbytes < 128) {
return nbytes + 2;
} else {
return nbytes + 3;
}
}
bool sch_pdu::has_space_ce(uint32_t nbytes)
{
if (rem_len >= nbytes + 1) {
return true;
} else {
return false;
}
}
bool sch_pdu::has_space_sdu(uint32_t nbytes)
{
if (rem_len >= size_plus_header_pdu(nbytes)) {
return true;
} else {
return false;
}
}
bool sch_pdu::update_space_ce(uint32_t nbytes)
{
if (has_space_ce(nbytes)) {
rem_len -= nbytes + 1;
}
}
bool sch_pdu::update_space_sdu(uint32_t nbytes)
{
if (has_space_sdu(nbytes)) {
rem_len -= size_plus_header_pdu(nbytes);
}
}
void sch_subh::init()
{
lcid = 0;
nof_bytes = 0;
sdu_payload_ptr = NULL;
bzero(ce_payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
}
sch_subh::cetype sch_subh::ce_type()
{
if (lcid >= PHD_REPORT) {
return (cetype) lcid;
} else {
return SDU;
}
}
uint32_t sch_subh::sizeof_ce(uint32_t lcid, bool is_ul)
{
if (is_ul) {
switch(lcid) {
case PHD_REPORT:
return 1;
case C_RNTI:
return 2;
case TRUNC_BSR:
return 1;
case SHORT_BSR:
return 1;
case LONG_BSR:
return 3;
case PADDING:
return 0;
}
} else {
switch(lcid) {
case CON_RES_ID:
return 6;
case TA_CMD:
return 1;
case DRX_CMD:
return 0;
case PADDING:
return 0;
}
}
}
bool sch_subh::is_sdu()
{
return ce_type() == SDU;
}
uint16_t sch_subh::get_c_rnti()
{
return *((uint16_t*) ce_payload);
}
uint64_t sch_subh::get_con_res_id()
{
return *((uint64_t*) ce_payload);
}
uint8_t sch_subh::get_phd()
{
return *((uint8_t*) ce_payload);
}
uint32_t sch_subh::get_sdu_lcid()
{
return *((uint32_t*) ce_payload);
}
uint32_t sch_subh::get_sdu_nbytes()
{
return *((uint32_t*) ce_payload);
}
uint8_t* sch_subh::get_sdu_ptr()
{
return sdu_payload_ptr;
}
uint8_t sch_subh::get_ta_cmd()
{
return *((uint8_t*) ce_payload);
}
void sch_subh::set_padding()
{
lcid = PADDING;
}
bool sch_subh::set_c_rnti(uint16_t crnti)
{
if (((sch_pdu*)parent)->has_space_ce(2)) {
*((uint16_t*) ce_payload) = crnti;
lcid = C_RNTI;
((sch_pdu*)parent)->update_space_ce(2);
return true;
} else {
return false;
}
}
bool sch_subh::set_con_res_id(uint64_t con_res_id)
{
if (((sch_pdu*)parent)->has_space_ce(6)) {
*((uint64_t*) ce_payload) = con_res_id;
lcid = CON_RES_ID;
((sch_pdu*)parent)->update_space_ce(6);
return true;
} else {
return false;
}
}
bool sch_subh::set_phd(uint8_t phd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
*((uint8_t*) ce_payload) = phd;
lcid = PHD_REPORT;
((sch_pdu*)parent)->update_space_ce(1);
return true;
} else {
return false;
}
}
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_)
{
if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_)) {
sdu_payload_ptr = ptr;
nof_bytes = nof_bytes_;
lcid = lcid_;
((sch_pdu*)parent)->update_space_sdu(nof_bytes_);
return true;
} else {
return false;
}
}
bool sch_subh::set_ta_cmd(uint8_t ta_cmd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
*((uint8_t*) ce_payload) = ta_cmd;
lcid = TA_CMD;
((sch_pdu*)parent)->update_space_ce(1);
return true;
} else {
return false;
}
}
// Section 6.2.1
void sch_subh::write_subheader(uint8_t** ptr, bool is_last)
{
if (is_sdu()) {
// MAC SDU: R/R/E/LCID/F/L subheader
srslte_bit_pack(0, ptr, 2); // R, R
srslte_bit_pack(is_last?1:0, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
// 2nd and 3rd octet
srslte_bit_pack(F_bit?1:0, ptr, 1); // F
srslte_bit_pack(nof_bytes, ptr, nof_bytes<128?7:15); // L
} else {
// MAC CE: R/R/E/LCID MAC Subheader
srslte_bit_pack(0, ptr, 2); // R, R
srslte_bit_pack(is_last?1:0, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
}
}
void sch_subh::write_payload(uint8_t** ptr)
{
if (is_sdu()) {
memcpy(*ptr, sdu_payload_ptr, nof_bytes*8*sizeof(uint8_t));
} else {
srslte_bit_pack_vector(ce_payload, *ptr, nof_bytes*8);
}
*ptr += nof_bytes*8;
}
bool sch_subh::read_subheader(uint8_t** ptr)
{
// Skip R
*ptr += 2;
bool e_bit = srslte_bit_unpack(ptr, 1)?true:false;
lcid = srslte_bit_unpack(ptr, 5);
if (is_sdu()) {
F_bit = srslte_bit_unpack(ptr, 1)?true:false;
nof_bytes = srslte_bit_unpack(ptr, F_bit?7:15);
} else {
nof_bytes = sizeof_ce(lcid, parent->is_ul());
}
return e_bit;
}
void sch_subh::read_payload(uint8_t** ptr)
{
if (is_sdu()) {
sdu_payload_ptr = *ptr;
} else {
srslte_bit_unpack_vector(ce_payload, *ptr, nof_bytes*8);
}
*ptr += nof_bytes*8;
}
void rar_pdu::fprint(FILE* stream)
{
fprintf(stream, "MAC PDU for RAR. ");
if (has_backoff_indicator) {
fprintf(stream, "Backoff Indicator %d. ", backoff_indicator);
}
pdu::fprint(stream);
}
void rar_subh::fprint(FILE* stream)
{
fprintf(stream, "RAPID: %d, Temp C-RNTI: %d, TA: %d, UL Grant: ", preamble, temp_rnti, ta);
srslte_vec_fprint_hex(stream, grant, 20);
}
rar_pdu::rar_pdu(uint32_t max_rars_) : pdu(max_rars_)
{
backoff_indicator = 0;
has_backoff_indicator = false;
}
uint8_t rar_pdu::get_backoff()
{
return backoff_indicator;
}
bool rar_pdu::has_backoff()
{
return has_backoff_indicator;
}
void rar_pdu::set_backoff(uint8_t bi)
{
has_backoff_indicator = true;
backoff_indicator = bi;
}
// Section 6.1.5
bool rar_pdu::write_packet(uint8_t* ptr)
{
// Write Backoff Indicator, if any
if (has_backoff_indicator) {
if (nof_subheaders > 0) {
srslte_bit_pack(1, &ptr, 1); // E
srslte_bit_pack(0, &ptr, 1); // T
srslte_bit_pack(0, &ptr, 2); // R, R
srslte_bit_pack(backoff_indicator, &ptr, 4);
}
}
// Write RAR subheaders
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].write_subheader(&ptr, i==nof_subheaders-1);
}
// Write payload
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].write_payload(&ptr);
}
// Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8);
}
void rar_subh::init()
{
bzero(grant, sizeof(uint8_t) * RAR_GRANT_LEN);
ta = 0;
temp_rnti = 0;
}
uint32_t rar_subh::get_rapid()
{
return preamble;
}
void rar_subh::get_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
{
memcpy(grant_, &grant, sizeof(uint8_t)*RAR_GRANT_LEN);
}
uint32_t rar_subh::get_ta_cmd()
{
return ta;
}
uint16_t rar_subh::get_temp_crnti()
{
return temp_rnti;
}
void rar_subh::set_rapid(uint32_t rapid)
{
preamble = rapid;
}
void rar_subh::set_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
{
memcpy(&grant, grant_, sizeof(uint8_t)*RAR_GRANT_LEN);
}
void rar_subh::set_ta_cmd(uint32_t ta_)
{
ta = ta_;
}
void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
{
temp_rnti = temp_rnti_;
}
// Section 6.2.2
void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
{
srslte_bit_pack(is_last?1:0, ptr, 1); // E
srslte_bit_pack(1, ptr, 1); // T
srslte_bit_pack(preamble, ptr, 6); // RAPID
}
// Section 6.2.3
void rar_subh::write_payload(uint8_t** ptr)
{
srslte_bit_pack(0, ptr, 1); // R
srslte_bit_pack(ta, ptr, 11); // Timing Adv Cmd
memcpy(*ptr, grant, 20*sizeof(uint8_t)); // UL grant
*ptr += 20;
srslte_bit_pack(temp_rnti, ptr, 16); // Temp C-RNTI
}
void rar_subh::read_payload(uint8_t** ptr)
{
*ptr += 1; // R
ta = srslte_bit_unpack(ptr, 11); // Timing Adv Cmd
memcpy(grant, *ptr, 20*sizeof(uint8_t)); // UL Grant
*ptr += 20;
temp_rnti = srslte_bit_unpack(ptr, 16); // Temp C-RNTI
}
bool rar_subh::read_subheader(uint8_t** ptr)
{
bool e_bit = srslte_bit_unpack(ptr, 1); // E
bool type = srslte_bit_unpack(ptr, 1); // T
if (type) {
preamble = srslte_bit_unpack(ptr, 6); // RAPID
} else {
// Read Backoff
*ptr += 2; // R, R
((rar_pdu*)parent)->set_backoff((uint8_t) srslte_bit_unpack(ptr, 4));
}
return e_bit;
}
}
}

@ -28,6 +28,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <signal.h>
#include "srsapps/ue/mac/mac_params.h" #include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac_io.h" #include "srsapps/ue/mac/mac_io.h"
@ -126,8 +127,9 @@ uint32_t interval(uint32_t x1, uint32_t x2) {
} }
} }
const char* state_str[10] = {"Idle", const char* state_str[11] = {"Idle",
"RA Initializat.: ", "RA Initializat.: ",
"RA Initial.Wait: ",
"RA ResSelection: ", "RA ResSelection: ",
"RA PreambleTx : ", "RA PreambleTx : ",
"RA PreambleRx : ", "RA PreambleRx : ",
@ -163,6 +165,15 @@ void ra_proc::process_timeadv_cmd(uint32_t tti, uint32_t ta) {
} }
} }
void* init_prach_thread(void *arg) {
phy* phy_h = (phy*) arg;
if (phy_h->init_prach()) {
return (void*) 0;
} else {
return (void*) -1;
}
}
void ra_proc::step_initialization() { void ra_proc::step_initialization() {
read_params(); read_params();
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED; pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
@ -172,10 +183,27 @@ void ra_proc::step_initialization() {
first_rar_received = true; first_rar_received = true;
mux_unit->msg3_flush(); mux_unit->msg3_flush();
backoff_param_ms = 0; backoff_param_ms = 0;
phy_h->init_prach(); if (pthread_create(&pt_init_prach, NULL, init_prach_thread, phy_h)) {
state = RESOURCE_SELECTION; perror("pthread_create");
rInfo("Done\n"); state = RA_PROBLEM;
} else {
state = INITIALIZATION_WAIT;
}
}
void ra_proc::step_initialization_wait() {
int n = pthread_kill(pt_init_prach, 0);
if (n) {
void *status;
pthread_join(pt_init_prach, &status);
if (status) {
rError("Initializing PRACH on PHY\n");
state = RA_PROBLEM;
} else {
rInfo("PRACH init OK\n");
state = RESOURCE_SELECTION;
}
}
} }
void ra_proc::step_resource_selection() { void ra_proc::step_resource_selection() {
@ -233,7 +261,6 @@ void ra_proc::step_response_reception() {
if (dl_buffer->get_dl_grant(&rar_grant)) if (dl_buffer->get_dl_grant(&rar_grant))
{ {
rInfo("DL grant found RA-RNTI=%d\n", ra_rnti); rInfo("DL grant found RA-RNTI=%d\n", ra_rnti);
if (rar_grant.get_tbs() > MAX_RAR_PDU_LEN) { if (rar_grant.get_tbs() > MAX_RAR_PDU_LEN) {
rError("RAR PDU exceeds local RAR PDU buffer (%d>%d)\n", rar_grant.get_tbs(), MAX_RAR_PDU_LEN); rError("RAR PDU exceeds local RAR PDU buffer (%d>%d)\n", rar_grant.get_tbs(), MAX_RAR_PDU_LEN);
state = RESPONSE_ERROR; state = RESPONSE_ERROR;
@ -241,28 +268,33 @@ void ra_proc::step_response_reception() {
} }
// Decode packet // Decode packet
dl_buffer->reset_softbuffer();
if (dl_buffer->decode_data(&rar_grant, rar_pdu_buffer)) { if (dl_buffer->decode_data(&rar_grant, rar_pdu_buffer)) {
rar_pdu.init(rar_grant.get_tbs()); rDebug("RAR decoded successfully TBS=%d\n", rar_grant.get_tbs());
rar_pdu_msg.init(rar_grant.get_tbs()/8);
rar_pdu_msg.parse_packet(rar_pdu_buffer);
rar_pdu_msg.fprint(stdout);
// Set Backoff parameter // Set Backoff parameter
if (rar_pdu.is_backoff()) { if (rar_pdu_msg.has_backoff()) {
backoff_param_ms = backoff_table[rar_pdu.get_backoff()%16]; backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff()%16];
} else { } else {
backoff_param_ms = 0; backoff_param_ms = 0;
} }
while(rar_pdu.read_next()) { while(rar_pdu_msg.next()) {
if (rar_pdu.get()->get_rapid() == sel_preamble) { if (rar_pdu_msg.get()->get_rapid() == sel_preamble) {
rInfo("Received RAPID=%d\n", sel_preamble); rInfo("Received RAPID=%d\n", sel_preamble);
process_timeadv_cmd(tti, rar_pdu.get()->get_ta_cmd()); process_timeadv_cmd(tti, rar_pdu_msg.get()->get_ta_cmd());
// FIXME: Indicate received target power // FIXME: Indicate received target power
//phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep); //phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep);
// Indicate grant to PHY layer. RAR grants have 6 sf delay (4 is the default delay) // Indicate grant to PHY layer. RAR grants have 6 sf delay (4 is the default delay)
uint8_t grant[mac_rar_pdu::mac_rar::RAR_GRANT_LEN]; uint8_t grant[rar_subh::RAR_GRANT_LEN];
rar_pdu.get()->get_sched_grant(grant); rar_pdu_msg.get()->get_sched_grant(grant);
phy_h->get_dl_buffer(tti+2)->set_rar_grant(grant); phy_h->get_dl_buffer(tti+2)->set_rar_grant(grant);
if (preambleIndex > 0) { if (preambleIndex > 0) {
@ -270,7 +302,7 @@ void ra_proc::step_response_reception() {
state = COMPLETION; state = COMPLETION;
} else { } else {
// Preamble selected by UE MAC // Preamble selected by UE MAC
params_db->set_param(mac_params::RNTI_TEMP, rar_pdu.get()->get_temp_crnti()); params_db->set_param(mac_params::RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti());
if (first_rar_received) { if (first_rar_received) {
first_rar_received = false; first_rar_received = false;
@ -287,23 +319,26 @@ void ra_proc::step_response_reception() {
} }
// Get TransportBlock size for the grant // Get TransportBlock size for the grant
ul_sched_grant msg3_grant(rar_pdu.get()->get_temp_crnti()); ul_sched_grant msg3_grant(sched_grant::RNTI_TYPE_TEMP, rar_pdu_msg.get()->get_temp_crnti());
phy_h->get_dl_buffer(tti+2)->get_ul_grant(&msg3_grant); phy_h->get_dl_buffer(tti+2)->get_ul_grant(&msg3_grant);
// Move MAC PDU from Multiplexing and assembly unit to Msg3 // Move MAC PDU from Multiplexing and assembly unit to Msg3
mux_unit->pdu_move_to_msg3(tti, msg3_grant.get_tbs()); // 56 is the minimum grant provided mux_unit->pdu_move_to_msg3(tti, msg3_grant.get_tbs()); // 56 is the minimum grant provided
}
rDebug("Going to Contention Resolution state\n");
state = CONTENTION_RESOLUTION; state = CONTENTION_RESOLUTION;
// Start contention resolution timer // Start contention resolution timer
timers_db->get(mac::CONTENTION_TIMER)->reset(); timers_db->get(mac::CONTENTION_TIMER)->reset();
timers_db->get(mac::CONTENTION_TIMER)->run(); timers_db->get(mac::CONTENTION_TIMER)->run();
} }
} else {
rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
} }
} }
} }
} }
} srslte_verbose = SRSLTE_VERBOSE_NONE;
} }
if (interval_ra > 3+responseWindowSize && interval_ra < 10000) { if (interval_ra > 3+responseWindowSize && interval_ra < 10000) {
rInfo("Timeout while trying to receive RAR\n"); rInfo("Timeout while trying to receive RAR\n");
@ -348,6 +383,7 @@ void ra_proc::step_contention_resolution() {
msg3_transmitted = true; msg3_transmitted = true;
if (pdcch_to_crnti_received != PDCCH_CRNTI_NOT_RECEIVED) if (pdcch_to_crnti_received != PDCCH_CRNTI_NOT_RECEIVED)
{ {
rInfo("PDCCH for C-RNTI received\n");
// Random Access initiated by MAC itself or PDCCH order (transmission of MAC C-RNTI CE) // Random Access initiated by MAC itself or PDCCH order (transmission of MAC C-RNTI CE)
if (start_mode == MAC_ORDER && pdcch_to_crnti_received == PDCCH_CRNTI_UL_GRANT || if (start_mode == MAC_ORDER && pdcch_to_crnti_received == PDCCH_CRNTI_UL_GRANT ||
start_mode == PDCCH_ORDER) start_mode == PDCCH_ORDER)
@ -363,6 +399,7 @@ void ra_proc::step_contention_resolution() {
// Random Access initiated by RRC by the transmission of CCCH SDU // Random Access initiated by RRC by the transmission of CCCH SDU
received_contention_id = demux_unit->get_contention_resolution_id(); received_contention_id = demux_unit->get_contention_resolution_id();
if (received_contention_id) { if (received_contention_id) {
rInfo("Received UE Contention Resolution ID\n");
// MAC PDU successfully decoded and contains MAC CE contention Id // MAC PDU successfully decoded and contains MAC CE contention Id
if (transmitted_contention_id == received_contention_id) { if (transmitted_contention_id == received_contention_id) {
@ -374,13 +411,17 @@ void ra_proc::step_contention_resolution() {
demux_unit->demultiplex_pending_pdu(tti); demux_unit->demultiplex_pending_pdu(tti);
state = COMPLETION; state = COMPLETION;
} else { } else {
rInfo("Transmitted UE Contention Id differs from received Contention ID\n");
// Discard MAC PDU // Discard MAC PDU
state = RESPONSE_ERROR; state = RESPONSE_ERROR;
} }
params_db->set_param(mac_params::RNTI_TEMP, 0); params_db->set_param(mac_params::RNTI_TEMP, 0);
} }
} }
} else {
rDebug("Msg3 not yet transmitted\n");
} }
} }
void ra_proc::step_completition() { void ra_proc::step_completition() {
@ -400,6 +441,9 @@ void ra_proc::step(uint32_t tti_)
case INITIALIZATION: case INITIALIZATION:
step_initialization(); step_initialization();
break; break;
case INITIALIZATION_WAIT:
step_initialization_wait();
break;
case RESOURCE_SELECTION: case RESOURCE_SELECTION:
step_resource_selection(); step_resource_selection();
break; break;
@ -430,6 +474,7 @@ void ra_proc::start_mac_order()
if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) { if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) {
start_mode = MAC_ORDER; start_mode = MAC_ORDER;
state = INITIALIZATION; state = INITIALIZATION;
run();
} }
} }
@ -438,6 +483,7 @@ void ra_proc::start_pdcch_order()
if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) { if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) {
start_mode = PDCCH_ORDER; start_mode = PDCCH_ORDER;
state = INITIALIZATION; state = INITIALIZATION;
run();
} }
} }
@ -446,12 +492,14 @@ void ra_proc::start_rlc_order()
if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) { if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) {
start_mode = RLC_ORDER; start_mode = RLC_ORDER;
state = INITIALIZATION; state = INITIALIZATION;
run();
} }
} }
// Contention Resolution Timer is expired (Section 5.1.5) // Contention Resolution Timer is expired (Section 5.1.5)
void ra_proc::timer_expired(uint32_t timer_id) void ra_proc::timer_expired(uint32_t timer_id)
{ {
rInfo("Contention Resolution Timer expired. Going to Response Error\n");
params_db->set_param(mac_params::RNTI_TEMP, 0); params_db->set_param(mac_params::RNTI_TEMP, 0);
state = RESPONSE_ERROR; state = RESPONSE_ERROR;
} }

@ -46,13 +46,13 @@ ul_harq_entity::ul_harq_entity() {
ul_harq_entity::~ul_harq_entity() { ul_harq_entity::~ul_harq_entity() {
delete proc; delete proc;
} }
bool ul_harq_entity::init(srslte_cell_t cell, uint32_t max_payload_len, log *log_h_, timers *timers_db_, mux *mux_unit_) { bool ul_harq_entity::init(srslte_cell_t cell, log *log_h_, timers *timers_db_, mux *mux_unit_) {
log_h = log_h_; log_h = log_h_;
mux_unit = mux_unit_; mux_unit = mux_unit_;
timers_db = timers_db_; timers_db = timers_db_;
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) { for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
if (!proc[i].init(cell, max_payload_len, this)) { if (!proc[i].init(cell, this)) {
return false; return false;
} }
} }
@ -79,15 +79,16 @@ void ul_harq_entity::reset_ndi() {
bool ul_harq_entity::is_sps(uint32_t pid) { bool ul_harq_entity::is_sps(uint32_t pid) {
return false; return false;
} }
// Called with no UL grant
void ul_harq_entity::run_tti(uint32_t tti, phy *phy_) { void ul_harq_entity::run_tti(uint32_t tti, dl_buffer *dl_buffer, phy *phy_) {
run_tti(tti, NULL, phy_); // TODO: Receive HARQ information from PHY (PHICH) and perform retransmissions
} }
// Implements Section 5.4.2.1 // Implements Section 5.4.2.1
// Called with UL grant
void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h) void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
{ {
uint32_t pid = pidof(tti); uint32_t pid = pidof(tti);
proc[pid].tti = tti;
last_retx_is_msg3 = false; last_retx_is_msg3 = false;
if (grant) { if (grant) {
@ -148,10 +149,9 @@ static int rv_of_irv[4] = {0, 2, 3, 1};
static int irv_of_rv[4] = {0, 3, 1, 2}; static int irv_of_rv[4] = {0, 3, 1, 2};
ul_harq_entity::ul_harq_process::ul_harq_process() : cur_grant(0) { ul_harq_entity::ul_harq_process::ul_harq_process() : cur_grant(0) {
payload = NULL;
max_payload_len = 0;
current_tx_nb = 0; current_tx_nb = 0;
current_irv = 0; current_irv = 0;
is_initiated = false;
is_grant_configured = false; is_grant_configured = false;
bzero(&cur_grant, sizeof(ul_sched_grant)); bzero(&cur_grant, sizeof(ul_sched_grant));
} }
@ -160,7 +160,9 @@ void ul_harq_entity::ul_harq_process::reset() {
current_irv = 0; current_irv = 0;
is_grant_configured = false; is_grant_configured = false;
bzero(&cur_grant, sizeof(ul_sched_grant)); bzero(&cur_grant, sizeof(ul_sched_grant));
if (is_initiated) {
srslte_softbuffer_tx_reset(&softbuffer); srslte_softbuffer_tx_reset(&softbuffer);
}
} }
bool ul_harq_entity::ul_harq_process::has_grant() { bool ul_harq_entity::ul_harq_process::has_grant() {
return is_grant_configured; return is_grant_configured;
@ -186,16 +188,14 @@ void ul_harq_entity::ul_harq_process::set_maxHARQ_Tx(uint32_t maxHARQ_Tx_, uint3
maxHARQ_Msg3Tx = maxHARQ_Msg3Tx_; maxHARQ_Msg3Tx = maxHARQ_Msg3Tx_;
} }
bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, uint32_t max_payload_len_, ul_harq_entity *parent) { bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, ul_harq_entity *parent) {
max_payload_len = max_payload_len_;
if (srslte_softbuffer_tx_init(&softbuffer, cell)) { if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
return false; return false;
} else { } else {
is_initiated = true;
harq_entity = parent; harq_entity = parent;
log_h = harq_entity->log_h; log_h = harq_entity->log_h;
payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len);
return payload?true:false;
} }
} }
@ -203,17 +203,16 @@ bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, uint32_t max_payl
void ul_harq_entity::ul_harq_process::generate_retx(ul_sched_grant* grant, ul_buffer* ul) void ul_harq_entity::ul_harq_process::generate_retx(ul_sched_grant* grant, ul_buffer* ul)
{ {
current_tx_nb++; current_tx_nb++;
if (grant) { if (grant) {
// HARQ entity requests an adaptive transmission // HARQ entity requests an adaptive transmission
memcpy(&cur_grant, grant, sizeof(grant)); memcpy(&cur_grant, grant, sizeof(grant));
current_irv = irv_of_rv[grant->get_rv()%4]; current_irv = irv_of_rv[grant->get_rv()%4];
harq_feedback = false; harq_feedback = false;
generate_tx(ul); generate_tx(NULL, ul);
} else { } else {
// HARQ entity requests a non-adaptive transmission // HARQ entity requests a non-adaptive transmission
if (!harq_feedback) { if (!harq_feedback) {
generate_tx(ul); generate_tx(NULL, ul);
} }
} }
@ -226,17 +225,17 @@ void ul_harq_entity::ul_harq_process::generate_retx(ul_sched_grant* grant, ul_bu
// New transmission (Section 5.4.2.2) // New transmission (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_new_tx(uint8_t *pdu_payload, bool is_msg3_, ul_sched_grant* ul_grant, ul_buffer* ul) void ul_harq_entity::ul_harq_process::generate_new_tx(uint8_t *pdu_payload, bool is_msg3_, ul_sched_grant* ul_grant, ul_buffer* ul)
{ {
if (ul_grant && pdu_payload && ul_grant->get_tbs() < max_payload_len) { if (ul_grant && pdu_payload) {
current_tx_nb = 0; current_tx_nb = 0;
current_irv = 0; current_irv = 0;
// Store MAC PDU in the HARQ buffer srslte_softbuffer_tx_reset(&softbuffer);
srslte_bit_pack_vector(pdu_payload, payload, ul_grant->get_tbs());
// Store the uplink grant // Store the uplink grant
memcpy(&cur_grant, ul_grant, sizeof(ul_grant)); memcpy(&cur_grant, ul_grant, sizeof(ul_sched_grant));
harq_feedback = false; harq_feedback = false;
generate_tx(ul); generate_tx(pdu_payload, ul);
is_grant_configured = true; is_grant_configured = true;
is_msg3 = is_msg3_; is_msg3 = is_msg3_;
Info("New %s transmission PDU Len %d bytes\n", is_msg3_?"Msg3":"", cur_grant.get_tbs());
} }
} }
@ -246,12 +245,13 @@ void ul_harq_entity::ul_harq_process::generate_retx(ul_buffer* ul)
} }
// Transmission of pending frame (Section 5.4.2.2) // Transmission of pending frame (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_tx(ul_buffer* ul) void ul_harq_entity::ul_harq_process::generate_tx(uint8_t *pdu_payload, ul_buffer* ul)
{ {
cur_grant.set_rv(rv_of_irv[current_irv%4]); cur_grant.set_rv(rv_of_irv[current_irv%4]);
ul->set_current_tx_nb(current_tx_nb); ul->set_current_tx_nb(current_tx_nb);
ul->generate_data(&cur_grant, &softbuffer, payload); ul->generate_data(&cur_grant, &softbuffer, pdu_payload);
current_irv = (current_irv+1)%4; current_irv = (current_irv+1)%4;
Info("UL transmission RV=%d, TBS=%d\n", cur_grant.get_rv(), cur_grant.get_tbs());
if (is_msg3) { if (is_msg3) {
if (current_tx_nb == maxHARQ_Msg3Tx) { if (current_tx_nb == maxHARQ_Msg3Tx) {
reset(); reset();

@ -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_common srsapps_radio srslte ${OPENLTE_LIBRARIES}) TARGET_LINK_LIBRARIES(mac_test srsapps_ue_mac srsapps_ue_phy srsapps_common srsapps_radio srslte ${OPENLTE_LIBRARIES} srslte_uhd)
ENDIF(UHD_FOUND AND OPENLTE_FOUND) ENDIF(UHD_FOUND AND OPENLTE_FOUND)

@ -122,9 +122,10 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
mac->set_param(srslte::ue::mac_params::RA_MAXTXMSG3, mac->set_param(srslte::ue::mac_params::RA_MAXTXMSG3,
sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx); sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx);
printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d\n", printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms\n",
liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles], liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles],
liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]); liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size],
liblte_rrc_mac_contention_resolution_timer_num[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]);
// PDSCH ConfigCommon // PDSCH ConfigCommon
mac->set_param(srslte::ue::mac_params::PDSCH_RSPOWER, mac->set_param(srslte::ue::mac_params::PDSCH_RSPOWER,
@ -133,6 +134,7 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
sib2->rr_config_common_sib.pdsch_cnfg.p_b); sib2->rr_config_common_sib.pdsch_cnfg.p_b);
// PUSCH ConfigCommon // PUSCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUSCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM, phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM,
sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam); sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam);
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET, phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET,
@ -150,12 +152,14 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u
phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT, phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch); sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch);
printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d\n", printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d, N_sb=%d\n",
sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset, sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch, sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift); sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift,
sib2->rr_config_common_sib.pusch_cnfg.n_sb);
// PUCCH ConfigCommon // PUCCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUCCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT, phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT,
liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]); liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]);
phy->set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT, phy->set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT,

@ -54,7 +54,9 @@ namespace ue {
bool get_dl_grant(dl_sched_grant *grant); bool get_dl_grant(dl_sched_grant *grant);
void discard_pending_rar_grant(); void discard_pending_rar_grant();
void set_rar_grant(srslte_dci_rar_grant_t *rar_grant); void set_rar_grant(srslte_dci_rar_grant_t *rar_grant);
void set_rar_grant(uint8_t grant[SRSLTE_RAR_GRANT_LEN]); void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]);
void release_pending_rar_grant();
void reset_softbuffer();
bool decode_ack(ul_sched_grant *pusch_grant); bool decode_ack(ul_sched_grant *pusch_grant);
bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK
bool decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload); bool decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload);

@ -68,7 +68,7 @@ bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_t
{ {
bool ret = false; bool ret = false;
if (signal_buffer) { if (signal_buffer) {
INFO("DL Buffer TTI %d: Receiving packet\n", tti); DEBUG("DL Buffer TTI %d: Receiving packet\n", tti);
cf_t *sf_buffer = NULL; cf_t *sf_buffer = NULL;
sf_symbols_and_ce_done = false; sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false; pdcch_llr_extracted = false;
@ -86,12 +86,14 @@ void dl_buffer::discard_pending_rar_grant() {
pending_rar_grant = false; pending_rar_grant = false;
} }
void dl_buffer::release_pending_rar_grant() {
pending_rar_grant = false;
}
bool dl_buffer::get_ul_grant(ul_sched_grant *grant) bool dl_buffer::get_ul_grant(ul_sched_grant *grant)
{ {
if (signal_buffer) { if (signal_buffer) {
printf("get_ul_grant tti=%d, is_temp_rnti=%d\n", tti, grant->is_temp_rnti());
if (pending_rar_grant && grant->is_temp_rnti()) { if (pending_rar_grant && grant->is_temp_rnti()) {
printf("Get pending RAR grant tti=%d\n", tti);
return grant->create_from_rar(&rar_grant, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET)); return grant->create_from_rar(&rar_grant, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
} else { } else {
if (!sf_symbols_and_ce_done) { if (!sf_symbols_and_ce_done) {
@ -117,39 +119,41 @@ bool dl_buffer::get_ul_grant(ul_sched_grant *grant)
} }
} }
void dl_buffer::set_rar_grant(uint8_t grant[SRSLTE_RAR_GRANT_LEN]) // Unpack RAR grant as defined in Section 6.2 of 36.213
void dl_buffer::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
{ {
srslte_dci_rar_grant_t rar_grant; pending_rar_grant = true;
srslte_dci_rar_grant_unpack(&rar_grant, grant_payload);
srslte_dci_rar_grant_fprint(stdout, &rar_grant);
} }
void dl_buffer::set_rar_grant(srslte_dci_rar_grant_t* rar_grant_) void dl_buffer::set_rar_grant(srslte_dci_rar_grant_t* rar_grant_)
{ {
printf("Set pending RAR grant tti=%d\n", tti);
pending_rar_grant = true; pending_rar_grant = true;
memcpy(&rar_grant, rar_grant_, sizeof(srslte_dci_rar_grant_t)); memcpy(&rar_grant, rar_grant_, sizeof(srslte_dci_rar_grant_t));
srslte_dci_rar_grant_fprint(stdout, &rar_grant);
} }
bool dl_buffer::get_dl_grant(dl_sched_grant *grant) bool dl_buffer::get_dl_grant(dl_sched_grant *grant)
{ {
if (signal_buffer && is_ready()) { if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Getting DL grant\n", tti); DEBUG("DL Buffer TTI %d: Getting DL grant\n", tti);
if (!sf_symbols_and_ce_done) { if (!sf_symbols_and_ce_done) {
INFO("DL Buffer TTI %d: Getting DL grant. Calling fft estimate\n", tti); DEBUG("DL Buffer TTI %d: Getting DL grant. Calling fft estimate\n", tti);
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) { if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false; return false;
} }
sf_symbols_and_ce_done = true; sf_symbols_and_ce_done = true;
} }
if (!pdcch_llr_extracted) { if (!pdcch_llr_extracted) {
INFO("DL Buffer TTI %d: Getting DL grant. extracting LLR\n", tti); DEBUG("DL Buffer TTI %d: Getting DL grant. extracting LLR\n", tti);
if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) { if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) {
return false; return false;
} }
pdcch_llr_extracted = true; pdcch_llr_extracted = true;
} }
if (SRSLTE_VERBOSE_ISINFO()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
srslte_vec_save_file((char*) "ce1", ue_dl.ce[0], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t)); srslte_vec_save_file((char*) "ce1", ue_dl.ce[0], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t));
srslte_vec_save_file((char*) "ce2", ue_dl.ce[1], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t)); srslte_vec_save_file((char*) "ce2", ue_dl.ce[1], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t));
srslte_vec_save_file((char*) "pdcch_d", ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce*sizeof(cf_t)); srslte_vec_save_file((char*) "pdcch_d", ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce*sizeof(cf_t));
@ -179,6 +183,11 @@ bool dl_buffer::decode_ack(ul_sched_grant *grant)
} }
} }
void dl_buffer::reset_softbuffer()
{
srslte_softbuffer_rx_reset(&ue_dl.softbuffer);
}
bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload) bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload)
{ {
return decode_data(grant, &ue_dl.softbuffer, payload); return decode_data(grant, &ue_dl.softbuffer, payload);
@ -187,9 +196,9 @@ bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload)
bool dl_buffer::decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload) bool dl_buffer::decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload)
{ {
if (signal_buffer && is_ready()) { if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti); DEBUG("DL Buffer TTI %d: Decoding PDSCH\n", tti);
if (!sf_symbols_and_ce_done) { if (!sf_symbols_and_ce_done) {
INFO("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti); DEBUG("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti);
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) { if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false; return false;
} }
@ -201,7 +210,7 @@ bool dl_buffer::decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softb
int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols, int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols,
ue_dl.ce, 0, grant->get_rnti(), payload); ue_dl.ce, 0, grant->get_rnti(), payload);
if (SRSLTE_VERBOSE_ISINFO()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.pdsch_cfg.grant.nof_re*sizeof(cf_t)); srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.pdsch_cfg.grant.nof_re*sizeof(cf_t));
} }
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {

@ -43,6 +43,7 @@ namespace ue {
bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_) bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_)
{ {
started = false; started = false;
radio_is_streaming = false;
ttisync = ttisync_; ttisync = ttisync_;
radio_handler = radio_handler_; radio_handler = radio_handler_;
ul_buffer_queue = new queue(6, sizeof(ul_buffer)); ul_buffer_queue = new queue(6, sizeof(ul_buffer));
@ -55,8 +56,7 @@ bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_)
pthread_attr_t attr; pthread_attr_t attr;
struct sched_param param; struct sched_param param;
param.sched_priority = 99; param.sched_priority = -20;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO); pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param); pthread_attr_setschedparam(&attr, &param);
@ -115,10 +115,10 @@ void phy::set_param(phy_params::phy_param_t param, int64_t value) {
// FIXME: Add PRACH power control // FIXME: Add PRACH power control
bool phy::send_prach(uint32_t preamble_idx) { bool phy::send_prach(uint32_t preamble_idx) {
send_prach(preamble_idx, -1, 0); return send_prach(preamble_idx, -1, 0);
} }
bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe) { bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe) {
send_prach(preamble_idx, allowed_subframe, 0); return send_prach(preamble_idx, allowed_subframe, 0);
} }
bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm) bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm)
{ {
@ -202,7 +202,8 @@ void* phy::phy_thread_fnc(void *arg) {
int radio_recv_wrapper_cs(void *h,void *data, uint32_t nsamples, srslte_timestamp_t *rx_time) int radio_recv_wrapper_cs(void *h,void *data, uint32_t nsamples, srslte_timestamp_t *rx_time)
{ {
radio *radio_handler = (radio*) h; radio *radio_handler = (radio*) h;
return radio_handler->rx_now(data, nsamples, rx_time); int n = radio_handler->rx_now(data, nsamples, rx_time);
return n;
} }
bool phy::set_cell(srslte_cell_t cell_) { bool phy::set_cell(srslte_cell_t cell_) {
@ -251,6 +252,9 @@ 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 + 6 < get_current_tti()) {
printf("Warning access to PHY too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti());
}
return (dl_buffer*) dl_buffer_queue->get(tti); return (dl_buffer*) dl_buffer_queue->get(tti);
} }

@ -42,7 +42,7 @@ namespace ue {
void prach::free_cell() void prach::free_cell()
{ {
if (initiated) { if (initiated) {
for (uint32_t i=0;i<64;i++) { for (int i=0;i<64;i++) {
if (buffer[i]) { if (buffer[i]) {
free(buffer[i]); free(buffer[i]);
} }
@ -69,12 +69,12 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
} }
len = prach_obj.N_seq + prach_obj.N_cp; len = prach_obj.N_seq + prach_obj.N_cp;
for (uint32_t i=0;i<64;i++) { for (int i=0;i<64;i++) {
buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t)); buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t));
if(!buffer[i]) { if(!buffer[i]) {
return false; return false;
} }
if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])){ if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])) {
return false; return false;
} }
} }
@ -86,10 +86,10 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
} }
bool prach::prepare_to_send(uint32_t preamble_idx_) { bool prach::prepare_to_send(uint32_t preamble_idx_) {
prepare_to_send(preamble_idx_, -1, 0); return prepare_to_send(preamble_idx_, -1, 0);
} }
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_) { bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_) {
prepare_to_send(preamble_idx_, allowed_subframe_, 0); return prepare_to_send(preamble_idx_, allowed_subframe_, 0);
} }
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, int target_power_dbm) bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, int target_power_dbm)
{ {
@ -129,7 +129,7 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
} }
} }
} }
INFO("PRACH Buffer: Not ready to send at tti: %d\n", current_tti_); DEBUG("PRACH Buffer: Not ready to send at tti: %d\n", current_tti_);
return false; return false;
} }
@ -149,12 +149,13 @@ bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time)
srslte_timestamp_add(&tx_time, 0, 1e-3*tx_advance_sf); srslte_timestamp_add(&tx_time, 0, 1e-3*tx_advance_sf);
// Correct CFO before transmission // Correct CFO before transmission
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 2*cfo / srslte_symbol_sz(cell.nof_prb)); srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 1.5*cfo/srslte_symbol_sz(cell.nof_prb));
// transmit // transmit
radio_handler->tx(signal_buffer, len, tx_time); radio_handler->tx(signal_buffer, len, tx_time);
INFO("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n", cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs); INFO("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n",
//srslte_vec_save_file("prach", buffer[preamble_idx], len*sizeof(cf_t)); cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs);
//srslte_vec_save_file("prach", buffer, len*sizeof(cf_t));
preamble_idx = -1; preamble_idx = -1;
} }

@ -28,6 +28,8 @@
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <pthread.h> #include <pthread.h>
#include <math.h>
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srsapps/ue/phy/sched_grant.h" #include "srsapps/ue/phy/sched_grant.h"
@ -99,8 +101,7 @@ bool ul_buffer::uci_ready() {
} }
bool ul_buffer::generate_data() { bool ul_buffer::generate_data() {
ul_sched_grant dummy(0); return generate_data(NULL, NULL);
return generate_data(&dummy, NULL);
} }
bool ul_buffer::generate_data(ul_sched_grant *grant, bool ul_buffer::generate_data(ul_sched_grant *grant,
@ -124,6 +125,7 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
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);
srslte_pusch_hopping_cfg_t pusch_hopping; srslte_pusch_hopping_cfg_t pusch_hopping;
if (grant) {
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t)); bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t));
pusch_hopping.n_sb = params_db->get_param(phy_params::PUSCH_HOPPING_N_SB); pusch_hopping.n_sb = params_db->get_param(phy_params::PUSCH_HOPPING_N_SB);
pusch_hopping.hop_mode = params_db->get_param(phy_params::PUSCH_HOPPING_INTRA_SF) ? pusch_hopping.hop_mode = params_db->get_param(phy_params::PUSCH_HOPPING_INTRA_SF) ?
@ -131,6 +133,7 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET); pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = grant->get_current_tx_nb(); pusch_hopping.current_tx_nb = grant->get_current_tx_nb();
}
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
@ -159,7 +162,7 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
int n = 0; int n = 0;
// Transmit on PUSCH if UL grant available, otherwise in PUCCH // Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (payload) { if (grant) {
grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg); grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg);
n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg, n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg,
@ -191,16 +194,26 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo
srslte_timestamp_t tx_time; srslte_timestamp_t tx_time;
srslte_timestamp_copy(&tx_time, &rx_time); srslte_timestamp_copy(&tx_time, &rx_time);
srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec); srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec);
INFO("Send PUSCH TTI: %d, CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us\n",
// Compute peak
float max = -1;
if (SRSLTE_VERBOSE_ISINFO()) {
float *t = (float*) signal_buffer;
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
}
}
}
INFO("Send PUSCH TTI: %d, CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us PeakAmplitude=%f\n",
tti, cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb), tti, 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); srslte_timestamp_real(&tx_time), time_adv_sec*1000000, max);
// Correct CFO before transmission // Correct CFO before transmission
srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, 1.5*cfo / srslte_symbol_sz(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);
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) TARGET_LINK_LIBRARIES(ue_itf_test_sib1 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) TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ENDIF(UHD_FOUND) ENDIF(UHD_FOUND)

@ -208,7 +208,7 @@ void config_phy() {
phy.set_param(srslte::ue::phy_params::PRACH_FREQ_OFFSET, 0); phy.set_param(srslte::ue::phy_params::PRACH_FREQ_OFFSET, 0);
phy.set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG, 0); phy.set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG, 0);
phy.set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, 0); phy.set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, 0);
phy.set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG, 1); phy.set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG, 4);
phy.set_param(srslte::ue::phy_params::PUSCH_BETA, 10); phy.set_param(srslte::ue::phy_params::PUSCH_BETA, 10);
phy.set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_HOPPING_EN, 0); phy.set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_HOPPING_EN, 0);
@ -233,6 +233,8 @@ uint32_t interval(uint32_t x1, uint32_t x2) {
} }
} }
srslte_softbuffer_rx_t softbuffer;
// This is the MAC implementation // This is the MAC implementation
void run_tti(uint32_t tti) { void run_tti(uint32_t tti) {
INFO("MAC running tti: %d\n", tti); INFO("MAC running tti: %d\n", tti);
@ -265,12 +267,10 @@ void run_tti(uint32_t tti) {
// Get DL grant for RA-RNTI=2 // Get DL grant for RA-RNTI=2
if (dl_buffer->get_dl_grant(&rar_grant)) if (dl_buffer->get_dl_grant(&rar_grant))
{ {
srslte_softbuffer_rx_reset(&softbuffer);
// Decode packet // Decode packet
if (dl_buffer->decode_data(&rar_grant, payload)) { if (dl_buffer->decode_data(&rar_grant, &softbuffer, payload)) {
rar_unpack(payload, &rar_msg); rar_unpack(payload, &rar_msg);
if (!prog_args.continous) {
printf("Received RAR for preamble %d\n", rar_msg.RAPID);
}
if (rar_msg.RAPID == preamble_idx) { if (rar_msg.RAPID == preamble_idx) {
INFO("Received RAR at TTI: %d\n", tti); INFO("Received RAR at TTI: %d\n", tti);
@ -358,6 +358,7 @@ void run_tti(uint32_t tti) {
state = RA; state = RA;
} }
} else { } else {
srslte_softbuffer_rx_reset(&softbuffer);
state = CONNSETUP; state = CONNSETUP;
} }
} }
@ -369,7 +370,7 @@ void run_tti(uint32_t tti) {
if (dl_buffer->get_dl_grant(&conn_setup_grant)) if (dl_buffer->get_dl_grant(&conn_setup_grant))
{ {
// Decode packet // Decode packet
if (dl_buffer->decode_data(&conn_setup_grant, payload)) { if (dl_buffer->decode_data(&conn_setup_grant, &softbuffer, payload)) {
nof_rx_connsetup++; nof_rx_connsetup++;
state = RA; state = RA;
nof_rtx_connsetup=0; nof_rtx_connsetup=0;
@ -397,6 +398,7 @@ void run_tti(uint32_t tti) {
state = RA; state = RA;
} }
} }
if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) { if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) {
printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r", printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r",
(float) 100*nof_rx_rar/nof_tx_ra, (float) 100*nof_rx_rar/nof_tx_ra,
@ -404,6 +406,7 @@ void run_tti(uint32_t tti) {
nof_rx_connsetup, nof_tx_ra); nof_rx_connsetup, nof_tx_ra);
} }
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -446,6 +449,13 @@ int main(int argc, char *argv[])
exit(-1); exit(-1);
} }
if (!phy.init_prach()) {
printf("Error initiating PRACH\n");
exit(-1);
}
srslte_softbuffer_rx_init(&softbuffer, cell);
/* Instruct the PHY to start RX streaming and synchronize */ /* Instruct the PHY to start RX streaming and synchronize */
if (!phy.start_rxtx()) { if (!phy.start_rxtx()) {
printf("Could not start RX\n"); printf("Could not start RX\n");

@ -50,11 +50,14 @@ add_executable(pdsch_enodeb pdsch_enodeb.c)
target_link_libraries(pdsch_enodeb srslte pthread) target_link_libraries(pdsch_enodeb srslte pthread)
IF(UHD_FOUND) IF(UHD_FOUND)
target_link_libraries(pdsch_ue srslte_uhd)
target_link_libraries(pdsch_enodeb srslte_uhd)
ELSE(UHD_FOUND) ELSE(UHD_FOUND)
add_definitions(-DDISABLE_UHD) add_definitions(-DDISABLE_UHD)
add_definitions(-DDISABLE_UHD)
ENDIF(UHD_FOUND) ENDIF(UHD_FOUND)
FIND_PACKAGE(SRSGUI)
IF(SRSGUI_FOUND) IF(SRSGUI_FOUND)
target_link_libraries(pdsch_ue ${SRSGUI_LIBRARIES}) target_link_libraries(pdsch_ue ${SRSGUI_LIBRARIES})
ELSE(SRSGUI_FOUND) ELSE(SRSGUI_FOUND)
@ -69,19 +72,19 @@ ENDIF(SRSGUI_FOUND)
IF(UHD_FOUND) IF(UHD_FOUND)
add_executable(cell_search cell_search.c) add_executable(cell_search cell_search.c)
target_link_libraries(cell_search srslte ) target_link_libraries(cell_search srslte srslte_uhd)
add_executable(prach_ue prach_ue.c) add_executable(prach_ue prach_ue.c)
target_link_libraries(prach_ue srslte ) target_link_libraries(prach_ue srslte srslte_uhd)
add_executable(cell_measurement cell_measurement.c) add_executable(cell_measurement cell_measurement.c)
target_link_libraries(cell_measurement srslte) target_link_libraries(cell_measurement srslte srslte_uhd)
add_executable(usrp_capture usrp_capture.c) add_executable(usrp_capture usrp_capture.c)
target_link_libraries(usrp_capture srslte) target_link_libraries(usrp_capture srslte srslte_uhd)
add_executable(usrp_capture_sync usrp_capture_sync.c) add_executable(usrp_capture_sync usrp_capture_sync.c)
target_link_libraries(usrp_capture_sync srslte) target_link_libraries(usrp_capture_sync srslte srslte_uhd)
MESSAGE(STATUS " UHD examples will be installed.") MESSAGE(STATUS " UHD examples will be installed.")

@ -327,6 +327,7 @@ int main(int argc, char **argv) {
printf("Tunning TX receiver to %.3f MHz\n", (double ) prog_args.uhd_tx_freq/1000000); printf("Tunning TX receiver to %.3f MHz\n", (double ) prog_args.uhd_tx_freq/1000000);
#ifdef kk
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell); ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error searching for cell\n"); fprintf(stderr, "Error searching for cell\n");
@ -335,6 +336,10 @@ int main(int argc, char **argv) {
printf("Cell not found\n"); printf("Cell not found\n");
exit(0); exit(0);
} }
#endif
cell.nof_prb = 50;
cell.id = 1;
cell.nof_ports = 1;
/* set sampling frequency */ /* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb); int srate = srslte_sampling_freq_hz(cell.nof_prb);
@ -471,7 +476,7 @@ int main(int argc, char **argv) {
cuhd_send_timed(uhd, prach_buffer, prach_buffer_len, cuhd_send_timed(uhd, prach_buffer, prach_buffer_len,
next_tx_time.full_secs, next_tx_time.frac_secs); next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue", prach_buffer, prach_buffer_len*sizeof(cf_t)); srslte_vec_save_file("prach_ue.dat", prach_buffer, prach_buffer_len*sizeof(cf_t));
ra_rnti = 2; ra_rnti = 2;
rar_window_start = sfn+1; rar_window_start = sfn+1;
@ -536,6 +541,8 @@ int main(int argc, char **argv) {
cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb), cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs); next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue_connreq.dat", ul_signal, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
//cuhd_start_rx_stream(uhd); //cuhd_start_rx_stream(uhd);
state = RECV_CONNSETUP; state = RECV_CONNSETUP;
conn_setup_trial = 0; conn_setup_trial = 0;

@ -27,13 +27,10 @@
IF(SRSGUI_FOUND AND UHD_FOUND) IF(SRSGUI_FOUND AND UHD_FOUND)
add_executable(pss pss.c) add_executable(pss pss.c)
target_link_libraries(pss srslte ${SRSGUI_LIBRARIES}) target_link_libraries(pss srslte ${SRSGUI_LIBRARIES} srslte_uhd)
add_executable(ue_rx ue_rx.c)
target_link_libraries(ue_rx srslte ${SRSGUI_LIBRARIES} pthread)
add_executable(simple_tx simple_tx.c) add_executable(simple_tx simple_tx.c)
target_link_libraries(simple_tx srslte) target_link_libraries(simple_tx srslte srslte_uhd)
ENDIF(SRSGUI_FOUND AND UHD_FOUND) ENDIF(SRSGUI_FOUND AND UHD_FOUND)

@ -1,629 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 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 Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include "srslte/srslte.h"
#ifndef DISABLE_UHD
#include "srslte/cuhd/cuhd.h"
#include "cuhd_utils.h"
cell_search_cfg_t cell_detect_config = {
5000,
100, // nof_frames_total
10.0 // threshold
};
#endif
//#define STDOUT_COMPACT
#ifndef DISABLE_GRAPHICS
#include "srsgui/srsgui.h"
void init_plots();
pthread_t plot_thread;
sem_t plot_sem;
uint32_t plot_sf_idx=0;
#endif
#define B210_DEFAULT_GAIN 40.0
#define B210_DEFAULT_GAIN_CORREC 110.0 // Gain of the Rx chain when the gain is set to 40
float gain_offset = B210_DEFAULT_GAIN_CORREC;
/**********************************************************************
* Program arguments processing
***********************************************************************/
typedef struct {
int nof_subframes;
bool disable_plots;
int force_N_id_2;
bool enable_cfo;
int time_offset;
uint16_t rnti;
char *input_file_name;
uint32_t file_nof_prb;
char *uhd_args;
float uhd_freq;
float uhd_freq_offset;
float uhd_gain;
int net_port;
char *net_address;
int net_port_signal;
char *net_address_signal;
}prog_args_t;
void args_default(prog_args_t *args) {
args->nof_subframes = -1;
args->rnti = SRSLTE_SIRNTI;
args->force_N_id_2 = -1; // Pick the best
args->input_file_name = NULL;
args->enable_cfo = true;
args->time_offset = 0;
args->file_nof_prb = 6;
args->uhd_args = "";
args->uhd_freq = -1.0;
args->uhd_freq = 8000000.0;
args->uhd_gain = 60.0;
args->net_port = -1;
args->net_address = "127.0.0.1";
args->net_port_signal = -1;
args->net_address_signal = "127.0.0.1";
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [agilcdnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
#ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain);
printf("\t-o UHD RX freq offset [Default %.1f MHz]\n", args->uhd_freq_offset/1000000);
#else
printf("\t UHD is disabled. CUHD library not available\n");
#endif
printf("\t-i input_file [Default USRP]\n");
printf("\t-p nof_prb for input file [Default %d]\n", args->file_nof_prb);
printf("\t-r RNTI [Default 0x%x]\n",args->rnti);
printf("\t-l Force N_id_2 [Default best]\n");
printf("\t-c Disable CFO correction [Default %s]\n", args->enable_cfo?"Enabled":"Disabled");
printf("\t-t Add time offset [Default %d]\n", args->time_offset);
#ifndef DISABLE_GRAPHICS
printf("\t-d disable plots [Default enabled]\n");
#else
printf("\t plots are disabled. Graphics library not available\n");
#endif
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
printf("\t-s remote UDP port to send input signal (-1 does nothing with it) [Default %d]\n", args->net_port_signal);
printf("\t-S remote UDP address to send input signal [Default %s]\n", args->net_address_signal);
printf("\t-u remote TCP port to send data (-1 does nothing with it) [Default %d]\n", args->net_port);
printf("\t-U remote TCP address to send data [Default %s]\n", args->net_address);
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "aoglipdnvrfctuUsS")) != -1) {
switch (opt) {
case 'i':
args->input_file_name = argv[optind];
break;
case 'p':
args->file_nof_prb = atoi(argv[optind]);
break;
case 'a':
args->uhd_args = argv[optind];
break;
case 'g':
args->uhd_gain = atof(argv[optind]);
break;
case 'o':
args->uhd_freq_offset = atof(argv[optind]);
break;
case 'f':
args->uhd_freq = atof(argv[optind]);
break;
case 'n':
args->nof_subframes = atoi(argv[optind]);
break;
case 'c':
args->enable_cfo = false;
break;
case 't':
args->time_offset = atoi(argv[optind]);
break;
case 'r':
args->rnti = atoi(argv[optind]);
break;
case 'l':
args->force_N_id_2 = atoi(argv[optind]);
break;
case 'u':
args->net_port = atoi(argv[optind]);
break;
case 'U':
args->net_address = argv[optind];
break;
case 's':
args->net_port_signal = atoi(argv[optind]);
break;
case 'S':
args->net_address_signal = argv[optind];
break;
case 'd':
args->disable_plots = true;
break;
case 'v':
srslte_verbose++;
break;
default:
usage(args, argv[0]);
exit(-1);
}
}
if (args->uhd_freq < 0 && args->input_file_name == NULL) {
usage(args, argv[0]);
exit(-1);
}
}
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t data[20000], data_packed[20000];
bool go_exit = false;
void sig_int_handler(int signo)
{
if (signo == SIGINT) {
go_exit = true;
}
}
#ifndef DISABLE_UHD
int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
}
#endif
extern float mean_exec_time;
enum receiver_state { DECODE_MIB, DECODE_PDSCH} state;
srslte_ue_dl_t ue_dl;
srslte_ue_sync_t ue_sync;
prog_args_t prog_args;
uint32_t sfn = 0; // system frame number
cf_t *sf_buffer = NULL;
srslte_netsink_t net_sink, net_sink_signal;
int main(int argc, char **argv) {
int ret;
srslte_cell_t cell;
int64_t sf_cnt;
srslte_ue_mib_t ue_mib;
#ifndef DISABLE_UHD
void *uhd;
#endif
uint32_t nof_trials = 0;
int n;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
uint32_t sfn_offset;
parse_args(&prog_args, argc, argv);
if (prog_args.net_port > 0) {
if (srslte_netsink_init(&net_sink, prog_args.net_address, prog_args.net_port, SRSLTE_NETSINK_TCP)) {
fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port);
exit(-1);
}
srslte_netsink_set_nonblocking(&net_sink);
}
if (prog_args.net_port_signal > 0) {
if (srslte_netsink_init(&net_sink_signal, prog_args.net_address_signal, prog_args.net_port_signal, SRSLTE_NETSINK_UDP)) {
fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address_signal, prog_args.net_port_signal);
exit(-1);
}
srslte_netsink_set_nonblocking(&net_sink_signal);
}
#ifndef DISABLE_UHD
if (!prog_args.input_file_name) {
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
/* Set receiver gain */
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
/* set receiver frequency */
cuhd_set_rx_freq_offset(uhd, (double) prog_args.uhd_freq, prog_args.uhd_freq_offset);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
} else if (ret == 0) {
printf("Cell not found\n");
exit(0);
}
/* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
cuhd_set_rx_srate(uhd, (double) srate);
} else {
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
return SRSLTE_ERROR;
}
INFO("Stopping UHD and flushing buffer...\r",0);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
if (srslte_ue_mib_init(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
}
#endif
/* If reading from file, go straight to PDSCH decoding. Otherwise, decode MIB first */
if (prog_args.input_file_name) {
state = DECODE_PDSCH;
/* preset cell configuration */
cell.id = 1;
cell.cp = SRSLTE_CP_NORM;
cell.phich_length = SRSLTE_PHICH_NORM;
cell.phich_resources = SRSLTE_PHICH_R_1;
cell.nof_ports = 1;
cell.nof_prb = prog_args.file_nof_prb;
if (srslte_ue_sync_init_file(&ue_sync, prog_args.file_nof_prb, prog_args.input_file_name)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
} else {
#ifndef DISABLE_UHD
state = DECODE_MIB;
if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
#endif
}
if (srslte_ue_dl_init(&ue_dl, cell)) { // This is the User RNTI
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
/* Initialize subframe counter */
sf_cnt = 0;
// Register Ctrl+C handler
signal(SIGINT, sig_int_handler);
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
init_plots(cell);
}
#endif
#ifndef DISABLE_UHD
if (!prog_args.input_file_name) {
cuhd_start_rx_stream(uhd);
}
#endif
// Variables for measurements
uint32_t nframes=0;
float rsrp=0.0, rsrq=0.0, snr=0.0;
bool decode_pdsch;
int pdcch_tx=0;
srslte_ra_dl_dci_t old_ra_dl;
bzero(&old_ra_dl, sizeof(srslte_ra_dl_dci_t));
ue_sync.correct_cfo = prog_args.enable_cfo;
/* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
}
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
switch (state) {
case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
exit(-1);
} else if (n == SRSLTE_UE_MIB_FOUND) {
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
srslte_cell_fprint(stdout, &cell, sfn);
printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset);
sfn = (sfn + sfn_offset)%1024;
state = DECODE_PDSCH;
}
}
break;
case DECODE_PDSCH:
if (prog_args.rnti != SRSLTE_SIRNTI) {
decode_pdsch = true;
} else {
/* We are looking for SIB1 Blocks, search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
decode_pdsch = true;
} else {
decode_pdsch = false;
}
}
if (decode_pdsch) {
if (prog_args.rnti != SRSLTE_SIRNTI) {
n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync));
} else {
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync), SRSLTE_SIRNTI,
((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
}
if (memcmp(&ue_dl.ra_dl, &old_ra_dl, sizeof(srslte_ra_dl_dci_t))) {
memcpy(&old_ra_dl, &ue_dl.ra_dl, sizeof(srslte_ra_dl_dci_t));
fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi);
printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format));
srslte_ra_pdsch_fprint(stdout, &old_ra_dl, cell.nof_prb);
}
if (n < 0) {
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
/* Send data if socket active */
if (prog_args.net_port > 0) {
srslte_bit_unpack_vector(data_packed, data, n);
srslte_netsink_write(&net_sink, data, 1+(n-1)/8);
}
}
nof_trials++;
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.05);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05);
snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&ue_dl.chest), snr, 0.01);
nframes++;
if (isnan(rsrq)) {
rsrq = 0;
}
if (isnan(snr)) {
snr = 0;
}
if (isnan(rsrp)) {
rsrp = 0;
}
#ifdef adjust_estimator
/* Adjust channel estimator based on SNR */
if (10*log10(snr) < 5.0) {
float f_low_snr[5]={0.05, 0.15, 0.6, 0.15, 0.05};
srslte_chest_dl_set_filter_freq(&ue_dl.chest, f_low_snr, 5);
} else if (10*log10(snr) < 10.0) {
float f_mid_snr[3]={0.1, 0.8, 0.1};
srslte_chest_dl_set_filter_freq(&ue_dl.chest, f_mid_snr, 3);
} else {
float f_high_snr[3]={0.05, 0.9, 0.05};
srslte_chest_dl_set_filter_freq(&ue_dl.chest, f_high_snr, 3);
}
#endif
}
if (srslte_ue_sync_get_sfidx(&ue_sync) != 5 && srslte_ue_sync_get_sfidx(&ue_sync) != 0) {
pdcch_tx++;
}
// Plot and Printf
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
#ifdef STDOUT_COMPACT
printf("SFN: %4d, PDCCH-Miss: %5.2f%% (%d missed), PDSCH-BLER: %5.2f%% (%d errors)\r",
sfn, 100*(1-(float) ue_dl.nof_detected/nof_trials),pdcch_tx-ue_dl.nof_detected,
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,ue_dl.pkt_errors);
#else
printf("CFO: %+6.2f KHz, SFO: %+6.2f Khz, "
"RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%% (%d), PDSCH-BLER: %5.2f%% (%d)\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
10*log10(rsrp*1000)-gain_offset,
10*log10(rsrq), 10*log10(snr),
100*(1-(float) ue_dl.nof_detected/nof_trials), pdcch_tx-ue_dl.nof_detected,
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total, ue_dl.pkt_errors);
#endif
}
break;
}
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
sfn++;
if (sfn == 1024) {
sfn = 0;
}
}
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
sem_post(&plot_sem);
}
#endif
} else if (ret == 0) {
printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
srslte_sync_get_peak_value(&ue_sync.sfind),
ue_sync.frame_total_cnt, ue_sync.state);
}
sf_cnt++;
} // Main loop
srslte_ue_dl_free(&ue_dl);
srslte_ue_sync_free(&ue_sync);
#ifndef DISABLE_UHD
if (!prog_args.input_file_name) {
srslte_ue_mib_free(&ue_mib);
cuhd_close(uhd);
}
#endif
printf("\nBye\n");
exit(0);
}
/**********************************************************************
* Plotting Functions
***********************************************************************/
#ifndef DISABLE_GRAPHICS
plot_real_t poutfft;
plot_real_t pce_angle, pce;
plot_scatter_t pscatequal, pscatequal_pdcch;
float tmp_plot[SRSLTE_SLOT_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)];
float tmp_plot2[SRSLTE_SLOT_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)];
float tmp_plot3[SRSLTE_SLOT_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)];
void *plot_thread_run(void *arg) {
int i;
uint32_t nof_re = SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp);
while(1) {
sem_wait(&plot_sem);
uint32_t nof_symbols = ue_dl.harq_process[0].dl_alloc.re_sf[plot_sf_idx];
for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
if (isinf(tmp_plot[i])) {
tmp_plot[i] = -80;
}
}
for (i = 0; i < SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0); i++) {
tmp_plot2[i] = 20 * log10f(cabsf(ue_dl.chest.pilot_estimates_average[0][i]));
if (isinf(tmp_plot2[i])) {
tmp_plot2[i] = -80;
}
}
for (i = 0; i < SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0); i++) {
tmp_plot3[i] = cargf(ue_dl.chest.pilot_estimates_average[0][i]);
}
plot_real_setNewData(&poutfft, tmp_plot, nof_re);
plot_real_setNewData(&pce, tmp_plot2, SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0));
plot_real_setNewData(&pce_angle, tmp_plot3, SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0));
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d, nof_symbols);
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce);
if (plot_sf_idx == 1) {
if (prog_args.net_port_signal > 0) {
srslte_netsink_write(&net_sink_signal, &sf_buffer[srslte_ue_sync_sf_len(&ue_sync)/7],
srslte_ue_sync_sf_len(&ue_sync));
}
}
}
return NULL;
}
void init_plots() {
sdrgui_init();
plot_real_init(&poutfft);
plot_real_setTitle(&poutfft, "Output FFT - Magnitude");
plot_real_setLabels(&poutfft, "Index", "dB");
plot_real_setYAxisScale(&poutfft, -40, 40);
plot_real_init(&pce);
plot_real_setTitle(&pce, "Channel Response - Magnitude");
plot_real_setLabels(&pce, "Index", "dB");
plot_real_init(&pce_angle);
plot_real_setTitle(&pce_angle, "Channel Response - Argument");
plot_real_setLabels(&pce_angle, "Index", "Radiants");
plot_real_setYAxisScale(&pce_angle, -M_PI, M_PI);
plot_scatter_init(&pscatequal);
plot_scatter_setTitle(&pscatequal, "PDSCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pscatequal, -2, 2);
plot_scatter_setYAxisScale(&pscatequal, -2, 2);
plot_scatter_init(&pscatequal_pdcch);
plot_scatter_setTitle(&pscatequal_pdcch, "PDCCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pscatequal_pdcch, -2, 2);
plot_scatter_setYAxisScale(&pscatequal_pdcch, -2, 2);
if (sem_init(&plot_sem, 0, 0)) {
perror("sem_init");
exit(-1);
}
if (pthread_create(&plot_thread, NULL, plot_thread_run, NULL)) {
perror("pthread_create");
exit(-1);
}
}
#endif

@ -120,6 +120,9 @@ SRSLTE_API int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar,
SRSLTE_API void srslte_dci_rar_grant_unpack(srslte_dci_rar_grant_t *rar, SRSLTE_API void srslte_dci_rar_grant_unpack(srslte_dci_rar_grant_t *rar,
uint8_t grant[SRSLTE_RAR_GRANT_LEN]); uint8_t grant[SRSLTE_RAR_GRANT_LEN]);
SRSLTE_API void srslte_dci_rar_grant_fprint(FILE *stream,
srslte_dci_rar_grant_t *rar);
SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char *str); SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char *str);
SRSLTE_API char* srslte_dci_format_string(srslte_dci_format_t format); SRSLTE_API char* srslte_dci_format_string(srslte_dci_format_t format);

@ -44,11 +44,6 @@ IF(FFTW3F_FOUND)
LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS}) LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS})
ENDIF(FFTW3F_FOUND) ENDIF(FFTW3F_FOUND)
IF(UHD_FOUND)
INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS})
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
ENDIF(UHD_FOUND)
IF(SRSGUI_FOUND) IF(SRSGUI_FOUND)
INCLUDE_DIRECTORIES(${SRSGUI_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${SRSGUI_INCLUDE_DIRS})
LINK_DIRECTORIES(${SRSGUI_LIBRARY_DIRS}) LINK_DIRECTORIES(${SRSGUI_LIBRARY_DIRS})
@ -62,20 +57,23 @@ FILE(GLOB modules *)
SET(SOURCES_ALL "") SET(SOURCES_ALL "")
FOREACH (_module ${modules}) FOREACH (_module ${modules})
IF(IS_DIRECTORY ${_module}) IF(IS_DIRECTORY ${_module})
IF ((NOT ${_module} MATCHES "cuhd") OR UHD_FOUND) IF (NOT ${_module} MATCHES "cuhd")
FILE(GLOB_RECURSE tmp "${_module}/src/*.c") FILE(GLOB_RECURSE tmp "${_module}/src/*.c")
LIST(APPEND SOURCES_ALL ${tmp}) LIST(APPEND SOURCES_ALL ${tmp})
FILE(GLOB_RECURSE tmp2 "${_module}/src/*.cpp") FILE(GLOB_RECURSE tmp2 "${_module}/src/*.cpp")
LIST(APPEND SOURCES_ALL ${tmp2}) LIST(APPEND SOURCES_ALL ${tmp2})
ENDIF ((NOT ${_module} MATCHES "cuhd") OR UHD_FOUND) ENDIF (NOT ${_module} MATCHES "cuhd")
ENDIF(IS_DIRECTORY ${_module}) ENDIF(IS_DIRECTORY ${_module})
ENDFOREACH() ENDFOREACH()
ADD_LIBRARY(srslte SHARED ${SOURCES_ALL}) ADD_LIBRARY(srslte SHARED ${SOURCES_ALL})
TARGET_LINK_LIBRARIES(srslte m ${FFTW3F_LIBRARIES}) TARGET_LINK_LIBRARIES(srslte m ${FFTW3F_LIBRARIES})
IF(UHD_FOUND) IF(UHD_FOUND)
TARGET_LINK_LIBRARIES(srslte ${UHD_LIBRARIES}) INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS})
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
ADD_LIBRARY(srslte_uhd SHARED ${CMAKE_CURRENT_SOURCE_DIR}/cuhd/src/cuhd_imp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cuhd/src/cuhd_utils.c)
TARGET_LINK_LIBRARIES(srslte_uhd ${UHD_LIBRARIES})
ENDIF(UHD_FOUND) ENDIF(UHD_FOUND)
INSTALL(TARGETS srslte DESTINATION ${LIBRARY_DIR}) INSTALL(TARGETS srslte DESTINATION ${LIBRARY_DIR})

@ -152,6 +152,15 @@ void srslte_dci_rar_grant_unpack(srslte_dci_rar_grant_t *rar, uint8_t grant[SRSL
rar->cqi_request = srslte_bit_unpack(&grant_ptr, 1)?true:false; rar->cqi_request = srslte_bit_unpack(&grant_ptr, 1)?true:false;
} }
void srslte_dci_rar_grant_fprint(FILE *stream, srslte_dci_rar_grant_t *rar) {
fprintf(stream, "RBA: %d, MCS: %d, TPC: %d, Hopping=%s, UL-Delay=%s, CQI=%s\n",
rar->rba, rar->trunc_mcs, rar->tpc_pusch,
rar->hopping_flag?"yes":"no",
rar->ul_delay?"yes":"no",
rar->cqi_request?"yes":"no"
);
}
/* Creates the UL PUSCH resource allocation grant from a DCI format 0 message /* Creates the UL PUSCH resource allocation grant from a DCI format 0 message
*/ */
int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, srslte_cell_t cell, int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, srslte_cell_t cell,
@ -171,7 +180,6 @@ int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, srslte_cell_t cell,
bzero(grant, sizeof(srslte_ra_ul_dci_t)); bzero(grant, sizeof(srslte_ra_ul_dci_t));
if (srslte_dci_msg_unpack_pusch(msg, ul_dci, cell.nof_prb)) { if (srslte_dci_msg_unpack_pusch(msg, ul_dci, cell.nof_prb)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
return ret; return ret;
} }
@ -379,8 +387,7 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (*y++ != 0) { if (*y++ != 0) {
fprintf(stderr, INFO("DCI message is Format1A\n", 0);
"Invalid format differentiation field value. This is SRSLTE_DCI_FORMAT1A\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (*y++ == 0) { if (*y++ == 0) {
@ -633,7 +640,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
} }
if (*y++ != 1) { if (*y++ != 1) {
fprintf(stderr, "Invalid format differentiation field value. This is SRSLTE_DCI_FORMAT0\n"); INFO("DCI message is Format0\n", 0);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

@ -215,7 +215,7 @@ uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c,
c[k].L = l; c[k].L = l;
c[k].ncce = ncce; c[k].ncce = ncce;
INFO("UE-specific SS Candidate %d: nCCE: %d, L: %d\n", DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n",
k, c[k].ncce, c[k].L); k, c[k].ncce, c[k].L);
k++; k++;
@ -223,7 +223,7 @@ uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c,
} }
} }
INFO("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x\n", k, rnti); DEBUG("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x\n", k, rnti);
return k; return k;
} }
@ -297,7 +297,7 @@ static int dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t E, ui
x = &data[nof_bits]; x = &data[nof_bits];
p_bits = (uint16_t) srslte_bit_unpack(&x, 16); p_bits = (uint16_t) srslte_bit_unpack(&x, 16);
crc_res = ((uint16_t) srslte_crc_checksum(&q->crc, data, nof_bits) & 0xffff); crc_res = ((uint16_t) srslte_crc_checksum(&q->crc, data, nof_bits) & 0xffff);
INFO("p_bits: 0x%x, crc_checksum: 0x%x, crc_rem: 0x%x\n", p_bits, crc_res, DEBUG("p_bits: 0x%x, crc_checksum: 0x%x, crc_rem: 0x%x\n", p_bits, crc_res,
p_bits ^ crc_res); p_bits ^ crc_res);
if (crc) { if (crc) {
@ -331,7 +331,7 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci
uint32_t nof_bits = srslte_dci_format_sizeof(format, q->cell.nof_prb); uint32_t nof_bits = srslte_dci_format_sizeof(format, q->cell.nof_prb);
uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location->L); uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location->L);
INFO("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);
ret = dci_decode(q, &q->llr[location->ncce * 72], ret = dci_decode(q, &q->llr[location->ncce * 72],
@ -369,7 +369,7 @@ int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLT
nof_symbols = e_bits/2; nof_symbols = e_bits/2;
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
INFO("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);
/* number of layers equals number of ports */ /* number of layers equals number of ports */
@ -427,7 +427,7 @@ static void crc_set_mask_rnti(uint8_t *crc, uint16_t rnti) {
uint8_t mask[16]; uint8_t mask[16];
uint8_t *r = mask; uint8_t *r = mask;
INFO("Mask CRC with RNTI 0x%x\n", rnti); DEBUG("Mask CRC with RNTI 0x%x\n", rnti);
srslte_bit_pack(rnti, &r, 16); srslte_bit_pack(rnti, &r, 16);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
@ -508,7 +508,7 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce && if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce &&
msg->nof_bits < SRSLTE_DCI_MAX_BITS) msg->nof_bits < SRSLTE_DCI_MAX_BITS)
{ {
INFO("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", DEBUG("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
msg->nof_bits, e_bits, location.ncce, location.L, rnti); msg->nof_bits, e_bits, location.ncce, location.L, rnti);
dci_encode(q, msg->data, q->e, msg->nof_bits, e_bits, rnti); dci_encode(q, msg->data, q->e, msg->nof_bits, e_bits, rnti);

@ -44,7 +44,7 @@
#define PHI_4 2 // PRACH phi parameter for format 4 #define PHI_4 2 // PRACH phi parameter for format 4
#define MAX_ROOTS 838 // Max number of root sequences #define MAX_ROOTS 838 // Max number of root sequences
#define PRACH_AMP 0.5 #define PRACH_AMP 0.4
/****************************************************** /******************************************************
* Reference tables from 3GPP TS 36.211 v10.7.0 * Reference tables from 3GPP TS 36.211 v10.7.0
@ -347,6 +347,8 @@ int srslte_prach_init(srslte_prach_t *p,
} }
} }
printf("N_cs=%d, ZCZC=%d\n", p->N_cs, p->zczc);
// Set up containers // Set up containers
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc); p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*p->N_zc); p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
@ -438,8 +440,9 @@ int srslte_prach_gen(srslte_prach_t *p,
// Copy preamble sequence into buffer // Copy preamble sequence into buffer
for(int i=0;i<p->N_seq;i++){ for(int i=0;i<p->N_seq;i++){
signal[p->N_cp+i] = PRACH_AMP*p->ifft_out[i%p->N_ifft_prach]; signal[p->N_cp+i] = p->ifft_out[i%p->N_ifft_prach];
} }
srslte_vec_sc_prod_cfc(signal, PRACH_AMP, signal, p->N_cp + p->N_seq);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }

@ -410,7 +410,6 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
data != NULL &&
cfg != NULL) cfg != NULL)
{ {
if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) { if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) {

@ -308,7 +308,7 @@ int regs_phich_init(srslte_regs_t *h) {
ni=((h->cell.id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8 ni=((h->cell.id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8
h->phich[mi].regs[i] = regs_phich[li][ni]; h->phich[mi].regs[i] = regs_phich[li][ni];
h->phich[mi].regs[i]->assigned = true; h->phich[mi].regs[i]->assigned = true;
INFO("Assigned PHICH REG#%d (%d,%d)\n",nreg,h->phich[mi].regs[i]->k0,li); DEBUG("Assigned PHICH REG#%d (%d,%d)\n",nreg,h->phich[mi].regs[i]->k0,li);
nreg++; nreg++;
} }
} }
@ -487,7 +487,7 @@ int regs_pcfich_init(srslte_regs_t *h) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} else { } else {
ch->regs[i]->assigned = true; ch->regs[i]->assigned = true;
INFO("Assigned PCFICH REG#%d (%d,0)\n", i, k); DEBUG("Assigned PCFICH REG#%d (%d,0)\n", i, k);
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;

@ -169,7 +169,6 @@ static int encode_tb(srslte_sch_t *q,
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
data != NULL &&
e_bits != NULL && e_bits != NULL &&
cb_segm != NULL && cb_segm != NULL &&
soft_buffer != NULL) soft_buffer != NULL)
@ -182,7 +181,7 @@ static int encode_tb(srslte_sch_t *q,
gamma = Gp%cb_segm->C; gamma = Gp%cb_segm->C;
} }
if (rv == 0) { if (data) {
/* Compute transport block CRC */ /* Compute transport block CRC */
par = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs); par = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs);
@ -226,7 +225,7 @@ static int encode_tb(srslte_sch_t *q,
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
cb_len, rlen - F, wp, rp, F, n_e); cb_len, rlen - F, wp, rp, F, n_e);
if (rv == 0) { if (data) {
/* Copy data to another buffer, making space for the Codeblock CRC */ /* Copy data to another buffer, making space for the Codeblock CRC */
if (i < cb_segm->C - 1) { if (i < cb_segm->C - 1) {

@ -89,7 +89,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
uint32_t nof_samples = srslte_sampling_freq_hz(n_ul_rb) * 0.003; uint32_t nof_samples = srslte_sampling_freq_hz(n_ul_rb) * 0.001;
cf_t *signal = srslte_vec_malloc(sizeof(cf_t) * nof_samples); cf_t *signal = srslte_vec_malloc(sizeof(cf_t) * nof_samples);
if (!signal) { if (!signal) {
@ -102,6 +102,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
srslte_vec_sc_prod_cfc(signal, 1.0/sqrtf(N_ifft_ul), signal, prach.N_seq+prach.N_cp);
if (nlhs >= 0) { if (nlhs >= 0) {
mexutils_write_cf(signal, &plhs[0], nof_samples, 1); mexutils_write_cf(signal, &plhs[0], nof_samples, 1);

@ -242,7 +242,7 @@ int sync_sss(srslte_sync_t *q, cf_t *input, uint32_t peak_pos, srslte_cp_t cp) {
/* Make sure we have enough room to find SSS sequence */ /* Make sure we have enough room to find SSS sequence */
sss_idx = (int) peak_pos-2*q->fft_size-SRSLTE_CP_LEN(q->fft_size, (SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM_LEN:SRSLTE_CP_EXT_LEN)); sss_idx = (int) peak_pos-2*q->fft_size-SRSLTE_CP_LEN(q->fft_size, (SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM_LEN:SRSLTE_CP_EXT_LEN));
if (sss_idx < 0) { if (sss_idx < 0) {
INFO("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos); DEBUG("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
DEBUG("Searching SSS around sss_idx: %d, peak_pos: %d\n", sss_idx, peak_pos); DEBUG("Searching SSS around sss_idx: %d, peak_pos: %d\n", sss_idx, peak_pos);
@ -321,14 +321,14 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
/* compute cumulative moving average CFO */ /* compute cumulative moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, CFO_EMA_ALPHA); q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, CFO_EMA_ALPHA);
} else { } else {
INFO("No space for CFO computation. Frame starts at \n",peak_pos); DEBUG("No space for CFO computation. Frame starts at \n",peak_pos);
} }
if (q->detect_cp) { if (q->detect_cp) {
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
q->cp = srslte_sync_detect_cp(q, input, peak_pos + find_offset); q->cp = srslte_sync_detect_cp(q, input, peak_pos + find_offset);
} else { } else {
INFO("Not enough room to detect CP length. Peak position: %d\n", peak_pos); DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos);
} }
} }
@ -343,7 +343,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
q->N_id_1 = 1000; q->N_id_1 = 1000;
if (sync_sss(q, input, find_offset + peak_pos, q->cp) < 0) { if (sync_sss(q, input, find_offset + peak_pos, q->cp) < 0) {
INFO("No space for SSS processing. Frame starts at %d\n", peak_pos); DEBUG("No space for SSS processing. Frame starts at %d\n", peak_pos);
} }
} }
// Return 1 (peak detected) even if we couldn't estimate CFO and SSS // Return 1 (peak detected) even if we couldn't estimate CFO and SSS
@ -352,7 +352,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
ret = 0; ret = 0;
} }
INFO("SYNC ret=%d N_id_2=%d find_offset=%d pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n", DEBUG("SYNC ret=%d N_id_2=%d find_offset=%d pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n",
ret, q->N_id_2, find_offset, peak_pos, q->peak_value, q->threshold, q->sf_idx, 15*q->mean_cfo); ret, q->N_id_2, find_offset, peak_pos, q->peak_value, q->threshold, q->sf_idx, 15*q->mean_cfo);
} else if (srslte_N_id_2_isvalid(q->N_id_2)) { } else if (srslte_N_id_2_isvalid(q->N_id_2)) {

@ -34,7 +34,7 @@ ENDIF(SRSGUI_FOUND)
IF(UHD_FOUND) IF(UHD_FOUND)
ADD_EXECUTABLE(pss_usrp pss_usrp.c) ADD_EXECUTABLE(pss_usrp pss_usrp.c)
TARGET_LINK_LIBRARIES(pss_usrp srslte) TARGET_LINK_LIBRARIES(pss_usrp srslte srslte_uhd)
IF(SRSGUI_FOUND) IF(SRSGUI_FOUND)
target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES}) target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES})
ELSE(SRSGUI_FOUND) ELSE(SRSGUI_FOUND)

@ -238,7 +238,7 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q, uint32_t N_id_2
q->candidates[nof_detected_frames].peak = q->ue_sync.strack.pss.peak_value; q->candidates[nof_detected_frames].peak = q->ue_sync.strack.pss.peak_value;
q->candidates[nof_detected_frames].psr = srslte_sync_get_peak_value(&q->ue_sync.strack); q->candidates[nof_detected_frames].psr = srslte_sync_get_peak_value(&q->ue_sync.strack);
q->candidates[nof_detected_frames].cfo = srslte_ue_sync_get_cfo(&q->ue_sync); q->candidates[nof_detected_frames].cfo = srslte_ue_sync_get_cfo(&q->ue_sync);
INFO DEBUG
("CELL SEARCH: [%3d/%3d/%d]: Found peak PSR=%.3f, Cell_id: %d CP: %s\n", ("CELL SEARCH: [%3d/%3d/%d]: Found peak PSR=%.3f, Cell_id: %d CP: %s\n",
nof_detected_frames, nof_scanned_frames, q->nof_frames_to_scan, nof_detected_frames, nof_scanned_frames, q->nof_frames_to_scan,
q->candidates[nof_detected_frames].psr, q->candidates[nof_detected_frames].cell_id, q->candidates[nof_detected_frames].psr, q->candidates[nof_detected_frames].cell_id,

@ -253,7 +253,7 @@ 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;
} }
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
} }
return crc_rem == rnti; return crc_rem == rnti;
} }
@ -289,7 +289,7 @@ 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;
} }
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
} }
} }
return crc_rem == rnti; return crc_rem == rnti;

@ -152,7 +152,7 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
srslte_ue_mib_reset(q); srslte_ue_mib_reset(q);
ret = SRSLTE_UE_MIB_FOUND; ret = SRSLTE_UE_MIB_FOUND;
} else { } else {
INFO("MIB not decoded: %u\n", q->frame_cnt); DEBUG("MIB not decoded: %u\n", q->frame_cnt);
q->frame_cnt++; q->frame_cnt++;
ret = SRSLTE_UE_MIB_NOTFOUND; ret = SRSLTE_UE_MIB_NOTFOUND;
} }
@ -222,7 +222,7 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
if (ret == 1) { if (ret == 1) {
mib_ret = srslte_ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset); mib_ret = srslte_ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset);
} else { } else {
INFO("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt);
srslte_ue_mib_reset(&q->ue_mib); srslte_ue_mib_reset(&q->ue_mib);
} }
nof_frames++; nof_frames++;

@ -265,16 +265,16 @@ static int find_peak_ok(srslte_ue_sync_t *q) {
/* Get the subframe index (0 or 5) */ /* Get the subframe index (0 or 5) */
q->sf_idx = srslte_sync_get_sf_idx(&q->sfind) + q->nof_recv_sf; q->sf_idx = srslte_sync_get_sf_idx(&q->sfind) + q->nof_recv_sf;
} else { } else {
INFO("Found peak at %d, SSS not detected\n", q->peak_idx); DEBUG("Found peak at %d, SSS not detected\n", q->peak_idx);
} }
q->frame_find_cnt++; q->frame_find_cnt++;
INFO("Found peak %d at %d, value %.3f, Cell_id: %d CP: %s\n", DEBUG("Found peak %d at %d, value %.3f, Cell_id: %d CP: %s\n",
q->frame_find_cnt, q->peak_idx, q->frame_find_cnt, q->peak_idx,
srslte_sync_get_last_peak_value(&q->sfind), q->cell.id, srslte_cp_string(q->cell.cp)); srslte_sync_get_last_peak_value(&q->sfind), q->cell.id, srslte_cp_string(q->cell.cp));
if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) { if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) {
INFO("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2); DEBUG("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2);
/* Receive the rest of the subframe so that we are subframe aligned*/ /* Receive the rest of the subframe so that we are subframe aligned*/
if (q->recv_callback(q->stream, q->input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) { if (q->recv_callback(q->stream, q->input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -299,7 +299,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
/* Make sure subframe idx is what we expect */ /* Make sure subframe idx is what we expect */
if ((q->sf_idx != srslte_sync_get_sf_idx(&q->strack)) && q->decode_sss_on_track) { if ((q->sf_idx != srslte_sync_get_sf_idx(&q->strack)) && q->decode_sss_on_track) {
INFO("Warning: Expected SF idx %d but got %d (%d,%g - %d,%g)!\n", DEBUG("Warning: Expected SF idx %d but got %d (%d,%g - %d,%g)!\n",
q->sf_idx, srslte_sync_get_sf_idx(&q->strack), q->sf_idx, srslte_sync_get_sf_idx(&q->strack),
q->strack.m0, q->strack.m0_value, q->strack.m1, q->strack.m1_value); q->strack.m0, q->strack.m0_value, q->strack.m1, q->strack.m1_value);
q->sf_idx = srslte_sync_get_sf_idx(&q->strack); q->sf_idx = srslte_sync_get_sf_idx(&q->strack);
@ -309,7 +309,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2 - (int) q->strack.fft_size); q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2 - (int) q->strack.fft_size);
if (q->time_offset) { if (q->time_offset) {
INFO("Time offset adjustment: %d samples\n", q->time_offset); DEBUG("Time offset adjustment: %d samples\n", q->time_offset);
} }
/* compute cumulative moving average time offset */ /* compute cumulative moving average time offset */
@ -318,7 +318,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
/* If the PSS peak is beyond the frame (we sample too slowly), /* If the PSS peak is beyond the frame (we sample too slowly),
discard the offseted samples to align next frame */ discard the offseted samples to align next frame */
if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) { if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) {
INFO("Positive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset); DEBUG("Positive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset);
if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) { if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) {
fprintf(stderr, "Error receiving from USRP\n"); fprintf(stderr, "Error receiving from USRP\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -338,10 +338,10 @@ static int track_peak_no(srslte_ue_sync_t *q) {
/* if we missed too many PSS go back to FIND */ /* if we missed too many PSS go back to FIND */
q->frame_no_cnt++; q->frame_no_cnt++;
if (q->frame_no_cnt >= TRACK_MAX_LOST) { if (q->frame_no_cnt >= TRACK_MAX_LOST) {
INFO("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt); DEBUG("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt);
q->state = SF_FIND; q->state = SF_FIND;
} else { } else {
INFO("Tracking peak not found. Peak %.3f, %d lost\n", DEBUG("Tracking peak not found. Peak %.3f, %d lost\n",
srslte_sync_get_last_peak_value(&q->strack), (int) q->frame_no_cnt); srslte_sync_get_last_peak_value(&q->strack), (int) q->frame_no_cnt);
} }
@ -398,7 +398,7 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
if (q->sf_idx == 10) { if (q->sf_idx == 10) {
q->sf_idx = 0; q->sf_idx = 0;
} }
INFO("Reading %d samples. sf_idx = %d\n", q->sf_len, q->sf_idx); DEBUG("Reading %d samples. sf_idx = %d\n", q->sf_len, q->sf_idx);
ret = 1; ret = 1;
*sf_symbols = q->input_buffer; *sf_symbols = q->input_buffer;
} else { } else {

@ -309,7 +309,6 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *
if (q != NULL && if (q != NULL &&
grant != NULL && grant != NULL &&
data != NULL &&
output_signal != NULL) output_signal != NULL)
{ {
@ -341,7 +340,6 @@ int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
if (q != NULL && if (q != NULL &&
cfg != NULL && cfg != NULL &&
data != NULL &&
output_signal != NULL) output_signal != NULL)
{ {
if (srslte_pusch_encode_rnti(&q->pusch, cfg, &q->softbuffer, data, rnti, q->sf_symbols)) { if (srslte_pusch_encode_rnti(&q->pusch, cfg, &q->softbuffer, data, rnti, q->sf_symbols)) {

Loading…
Cancel
Save