mirror of https://github.com/PentHertz/srsLTE.git
Improvements in prach detection
This commit is contained in:
parent
9618135423
commit
cc00b172b5
|
@ -1,22 +1,23 @@
|
||||||
%% PRACH Detection Conformance Test
|
%% PRACH Detection Conformance Test
|
||||||
clear
|
%clear
|
||||||
|
|
||||||
d=18;%linspace(4,14,6);
|
d=50;%linspace(4,14,6);
|
||||||
pDetection2 = zeros(2,length(d));
|
pDetection2 = zeros(2,length(d));
|
||||||
for dd=1:length(d)
|
for dd=1:length(d)
|
||||||
detect_factor=d(dd);
|
detect_factor=d(dd);
|
||||||
|
|
||||||
numSubframes = 75; % Number of subframes frames to simulate at each SNR
|
numSubframes = 1; % Number of subframes frames to simulate at each SNR
|
||||||
SNRdB = linspace(-14,10,8); % SNR points to simulate
|
SNRdB = 10;%linspace(-14,10,8); % SNR points to simulate
|
||||||
foffset = 300.0; % Frequency offset in Hertz
|
foffset = 0.0; % Frequency offset in Hertz
|
||||||
add_fading=true;
|
delay=0;
|
||||||
|
add_fading=false;
|
||||||
|
|
||||||
addpath('../../build/srslte/lib/phch/test')
|
addpath('../../build/srslte/lib/phch/test')
|
||||||
|
|
||||||
%% UE Configuration
|
%% UE Configuration
|
||||||
% User Equipment (UE) settings are specified in the structure |ue|.
|
% User Equipment (UE) settings are specified in the structure |ue|.
|
||||||
|
|
||||||
ue.NULRB = 100; % 6 Resource Blocks
|
ue.NULRB = 15; % 6 Resource Blocks
|
||||||
ue.DuplexMode = 'FDD'; % Frequency Division Duplexing (FDD)
|
ue.DuplexMode = 'FDD'; % Frequency Division Duplexing (FDD)
|
||||||
ue.CyclicPrefixUL = 'Normal'; % Normal cyclic prefix length
|
ue.CyclicPrefixUL = 'Normal'; % Normal cyclic prefix length
|
||||||
ue.NTxAnts = 1; % Number of transmission antennas
|
ue.NTxAnts = 1; % Number of transmission antennas
|
||||||
|
@ -25,8 +26,7 @@ ue.NTxAnts = 1; % Number of transmission antennas
|
||||||
|
|
||||||
prach.Format = 0; % PRACH format: TS36.104, Table 8.4.2.1-1
|
prach.Format = 0; % PRACH format: TS36.104, Table 8.4.2.1-1
|
||||||
prach.HighSpeed = 0; % Normal mode: TS36.104, Table 8.4.2.1-1
|
prach.HighSpeed = 0; % Normal mode: TS36.104, Table 8.4.2.1-1
|
||||||
prach.FreqOffset = 0; % Default frequency location
|
prach.FreqOffset = 4; % Default frequency location
|
||||||
|
|
||||||
info = ltePRACHInfo(ue, prach); % PRACH information
|
info = ltePRACHInfo(ue, prach); % PRACH information
|
||||||
|
|
||||||
%% Propagation Channel Configuration
|
%% Propagation Channel Configuration
|
||||||
|
@ -67,9 +67,9 @@ for nSNR = 1:length(SNRdB)
|
||||||
% Loop for each subframe
|
% Loop for each subframe
|
||||||
for nsf = 1:numSubframes
|
for nsf = 1:numSubframes
|
||||||
|
|
||||||
prach.SeqIdx = randi(838,1,1)-1; % Logical sequence index: TS36.141, Table A.6-1
|
prach.SeqIdx = 0;%randi(838,1,1)-1; % Logical sequence index: TS36.141, Table A.6-1
|
||||||
prach.CyclicShiftIdx = randi(16,1,1)-1; % Cyclic shift index: TS36.141, Table A.6-1
|
prach.CyclicShiftIdx = 11;%randi(16,1,1)-1; % Cyclic shift index: TS36.141, Table A.6-1
|
||||||
prach.PreambleIdx = randi(64,1,1)-1; % Preamble index: TS36.141, Table A.6-1
|
prach.PreambleIdx = 1;%randi(64,1,1)-1; % Preamble index: TS36.141, Table A.6-1
|
||||||
info = ltePRACHInfo(ue, prach); % PRACH information
|
info = ltePRACHInfo(ue, prach); % PRACH information
|
||||||
|
|
||||||
% PRACH transmission
|
% PRACH transmission
|
||||||
|
@ -77,8 +77,8 @@ for nSNR = 1:length(SNRdB)
|
||||||
ue.NFrame = fix((nsf-1)/10);
|
ue.NFrame = fix((nsf-1)/10);
|
||||||
|
|
||||||
% Set PRACH timing offset in us as per TS36.141, Figure 8.4.1.4.2-2
|
% Set PRACH timing offset in us as per TS36.141, Figure 8.4.1.4.2-2
|
||||||
prach.TimingOffset = info.BaseOffset + ue.NSubframe/10.0;
|
%prach.TimingOffset = info.BaseOffset + ue.NSubframe/10.0;
|
||||||
% prach.TimingOffset = 0;
|
prach.TimingOffset = 0;
|
||||||
|
|
||||||
% Generate transmit wave
|
% Generate transmit wave
|
||||||
[txwave,prachinfo] = ltePRACH(ue, prach);
|
[txwave,prachinfo] = ltePRACH(ue, prach);
|
||||||
|
@ -92,23 +92,30 @@ for nSNR = 1:length(SNRdB)
|
||||||
rxwave = txwave;
|
rxwave = txwave;
|
||||||
end
|
end
|
||||||
% Add noise
|
% Add noise
|
||||||
noise = N*complex(randn(size(rxwave)), randn(size(rxwave)));
|
%noise = N*complex(randn(size(rxwave)), randn(size(rxwave)));
|
||||||
rxwave = rxwave + noise;
|
%rxwave = rxwave + noise;
|
||||||
|
|
||||||
% Remove the implementation delay of the channel modeling
|
% Remove the implementation delay of the channel modeling
|
||||||
if (add_fading)
|
if (add_fading)
|
||||||
rxwave = rxwave((fadinginfo.ChannelFilterDelay + 1):end, :);
|
rxwave = rxwave((fadinginfo.ChannelFilterDelay + 1):end, :);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
rxwave=x;
|
||||||
|
% rxwave=[zeros(delay,1); txwave(1:end-delay)];
|
||||||
|
|
||||||
% Apply frequency offset
|
% Apply frequency offset
|
||||||
t = ((0:size(rxwave, 1)-1)/chcfg.SamplingRate).';
|
t = ((0:size(rxwave, 1)-1)/chcfg.SamplingRate).';
|
||||||
rxwave = rxwave .* repmat(exp(1i*2*pi*foffset*t), ...
|
rxwave = rxwave .* repmat(exp(1i*2*pi*foffset*t), ...
|
||||||
1, size(rxwave, 2));
|
1, size(rxwave, 2));
|
||||||
|
|
||||||
|
|
||||||
% PRACH detection for all cell preamble indices
|
% PRACH detection for all cell preamble indices
|
||||||
[detected, offsets] = ltePRACHDetect(ue, prach, rxwave, (0:63).');
|
[detected, offsets] = ltePRACHDetect(ue, prach, rxwave, (0:63).');
|
||||||
|
|
||||||
[detected_srs, offsets_srs] = srslte_prach_detect(ue, prach, rxwave, detect_factor);
|
[detected_srs, offsets_srs, corrout] = srslte_prach_detect(ue, prach, rxwave, detect_factor);
|
||||||
|
|
||||||
|
disp(detected)
|
||||||
|
disp(detected_srs)
|
||||||
|
disp(offsets_srs*1e6)
|
||||||
|
|
||||||
% Test for preamble detection
|
% Test for preamble detection
|
||||||
if (length(detected)==1)
|
if (length(detected)==1)
|
||||||
|
@ -144,7 +151,7 @@ for nSNR = 1:length(SNRdB)
|
||||||
% Calculate timing estimation error. The true offset is
|
% Calculate timing estimation error. The true offset is
|
||||||
% PRACH offset plus channel delay
|
% PRACH offset plus channel delay
|
||||||
trueOffset = prach.TimingOffset/1e6 + 310e-9;
|
trueOffset = prach.TimingOffset/1e6 + 310e-9;
|
||||||
measuredOffset = offsets_srs(1)/1e6;
|
measuredOffset = offsets_srs(1);
|
||||||
timingerror = abs(measuredOffset-trueOffset);
|
timingerror = abs(measuredOffset-trueOffset);
|
||||||
|
|
||||||
% Test for acceptable timing error
|
% Test for acceptable timing error
|
||||||
|
@ -189,3 +196,4 @@ else
|
||||||
fprintf('Pdet=%.4f%%, Pdet_srs=%.4f%%\n',pDetection(1,nSNR),pDetection(2,nSNR))
|
fprintf('Pdet=%.4f%%, Pdet_srs=%.4f%%\n',pDetection(1,nSNR),pDetection(2,nSNR))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
plot(corrout)
|
||||||
|
|
|
@ -500,7 +500,6 @@ int main(int argc, char **argv) {
|
||||||
decode_pdsch = false;
|
decode_pdsch = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode_pdsch) {
|
if (decode_pdsch) {
|
||||||
INFO("Attempting DL decode SFN=%d\n", sfn);
|
INFO("Attempting DL decode SFN=%d\n", sfn);
|
||||||
if (prog_args.rnti != SRSLTE_SIRNTI) {
|
if (prog_args.rnti != SRSLTE_SIRNTI) {
|
||||||
|
@ -509,7 +508,6 @@ int main(int argc, char **argv) {
|
||||||
// RV for SIB1 is predefined
|
// RV for SIB1 is predefined
|
||||||
uint32_t k = (sfn/2)%4;
|
uint32_t k = (sfn/2)%4;
|
||||||
uint32_t rv = ((uint32_t) ceilf((float)1.5*k))%4;
|
uint32_t rv = ((uint32_t) ceilf((float)1.5*k))%4;
|
||||||
|
|
||||||
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data,
|
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data,
|
||||||
srslte_ue_sync_get_sfidx(&ue_sync),
|
srslte_ue_sync_get_sfidx(&ue_sync),
|
||||||
SRSLTE_SIRNTI, rv);
|
SRSLTE_SIRNTI, rv);
|
||||||
|
|
|
@ -86,7 +86,6 @@ typedef struct SRSLTE_API {
|
||||||
cf_t pss_signal[SRSLTE_PSS_LEN];
|
cf_t pss_signal[SRSLTE_PSS_LEN];
|
||||||
float sss_signal0[SRSLTE_SSS_LEN];
|
float sss_signal0[SRSLTE_SSS_LEN];
|
||||||
float sss_signal5[SRSLTE_SSS_LEN];
|
float sss_signal5[SRSLTE_SSS_LEN];
|
||||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
|
||||||
|
|
||||||
uint32_t nof_rnti;
|
uint32_t nof_rnti;
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,8 @@ SRSLTE_API int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q,
|
||||||
uint32_t freq_offset,
|
uint32_t freq_offset,
|
||||||
cf_t *signal,
|
cf_t *signal,
|
||||||
uint32_t *indices,
|
uint32_t *indices,
|
||||||
uint32_t *offsets);
|
float *offsets,
|
||||||
|
float *peak2avg);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -64,6 +64,7 @@ typedef struct SRSLTE_API {
|
||||||
uint32_t N_zc; // PRACH sequence length
|
uint32_t N_zc; // PRACH sequence length
|
||||||
uint32_t N_cs; // Cyclic shift size
|
uint32_t N_cs; // Cyclic shift size
|
||||||
uint32_t N_seq; // Preamble length
|
uint32_t N_seq; // Preamble length
|
||||||
|
float T_seq; // Preamble length in seconds
|
||||||
uint32_t N_cp; // Cyclic prefix length
|
uint32_t N_cp; // Cyclic prefix length
|
||||||
|
|
||||||
// Generated tables
|
// Generated tables
|
||||||
|
@ -153,7 +154,8 @@ SRSLTE_API int srslte_prach_detect_offset(srslte_prach_t *p,
|
||||||
cf_t *signal,
|
cf_t *signal,
|
||||||
uint32_t sig_len,
|
uint32_t sig_len,
|
||||||
uint32_t *indices,
|
uint32_t *indices,
|
||||||
uint32_t *offsets,
|
float *t_offsets,
|
||||||
|
float *peak_to_avg,
|
||||||
uint32_t *ind_len);
|
uint32_t *ind_len);
|
||||||
|
|
||||||
SRSLTE_API void srslte_prach_set_detect_factor(srslte_prach_t *p,
|
SRSLTE_API void srslte_prach_set_detect_factor(srslte_prach_t *p,
|
||||||
|
|
|
@ -175,9 +175,11 @@ void srslte_enb_dl_put_refs(srslte_enb_dl_t *q, uint32_t sf_idx)
|
||||||
|
|
||||||
void srslte_enb_dl_put_mib(srslte_enb_dl_t *q, uint32_t tti)
|
void srslte_enb_dl_put_mib(srslte_enb_dl_t *q, uint32_t tti)
|
||||||
{
|
{
|
||||||
|
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||||
|
|
||||||
if ((tti%10) == 0) {
|
if ((tti%10) == 0) {
|
||||||
srslte_pbch_mib_pack(&q->cell, tti/10, q->bch_payload);
|
srslte_pbch_mib_pack(&q->cell, tti/10, bch_payload);
|
||||||
srslte_pbch_encode(&q->pbch, q->bch_payload, q->slot1_symbols, ((tti/10)%4));
|
srslte_pbch_encode(&q->pbch, bch_payload, q->slot1_symbols, ((tti/10)%4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,13 +239,16 @@ int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant,
|
||||||
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) {
|
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) {
|
||||||
rnti_is_user = false;
|
rnti_is_user = false;
|
||||||
}
|
}
|
||||||
//srslte_ra_pdsch_fprint(stdout, grant, q->cell.nof_prb);
|
|
||||||
srslte_dci_msg_pack_pdsch(grant, &dci_msg, format, q->cell.nof_prb, rnti_is_user);
|
srslte_dci_msg_pack_pdsch(grant, &dci_msg, format, q->cell.nof_prb, rnti_is_user);
|
||||||
//srslte_vec_fprint_hex(stdout, dci_msg.data, dci_msg.nof_bits);
|
|
||||||
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
|
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
|
||||||
fprintf(stderr, "Error encoding DCI message\n");
|
fprintf(stderr, "Error encoding DCI message\n");
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
/* printf("format: %s, sf_idx=%d, rnti=%d, location=%d,%d, cfi=%d\n",
|
||||||
|
srslte_dci_format_string(format), sf_idx, rnti, location.L, location.ncce, q->cfi);
|
||||||
|
srslte_ra_pdsch_fprint(stdout, grant, q->cell.nof_prb);
|
||||||
|
srslte_vec_fprint_hex(stdout, dci_msg.data, dci_msg.nof_bits);
|
||||||
|
*/
|
||||||
|
|
||||||
return SRSLTE_SUCCESS;
|
return SRSLTE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,8 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
|
||||||
fprintf(stderr, "Error initiating PRACH\n");
|
fprintf(stderr, "Error initiating PRACH\n");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srslte_prach_set_detect_factor(&q->prach, 60);
|
||||||
|
|
||||||
if (srslte_chest_ul_init(&q->chest, cell)) {
|
if (srslte_chest_ul_init(&q->chest, cell)) {
|
||||||
fprintf(stderr, "Error initiating channel estimator\n");
|
fprintf(stderr, "Error initiating channel estimator\n");
|
||||||
|
@ -177,18 +179,20 @@ int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srs
|
||||||
|
|
||||||
int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q, uint32_t tti,
|
int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q, uint32_t tti,
|
||||||
uint32_t freq_offset, cf_t *signal,
|
uint32_t freq_offset, cf_t *signal,
|
||||||
uint32_t *indices, uint32_t *offsets)
|
uint32_t *indices, float *offsets, float *peak2avg)
|
||||||
{
|
{
|
||||||
uint32_t nof_detected_prach = 0;
|
uint32_t nof_detected_prach = 0;
|
||||||
// consider the number of subframes the transmission must be anticipated
|
// consider the number of subframes the transmission must be anticipated
|
||||||
if (srslte_prach_tti_opportunity(&q->prach, tti, -1))
|
if (srslte_prach_tti_opportunity(&q->prach, tti, -1))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (srslte_prach_detect_offset(&q->prach,
|
if (srslte_prach_detect_offset(&q->prach,
|
||||||
freq_offset,
|
freq_offset,
|
||||||
&signal[q->prach.N_cp],
|
&signal[q->prach.N_cp],
|
||||||
SRSLTE_SF_LEN_PRB(q->cell.nof_prb),
|
SRSLTE_SF_LEN_PRB(q->cell.nof_prb),
|
||||||
indices,
|
indices,
|
||||||
offsets,
|
offsets,
|
||||||
|
peak2avg,
|
||||||
&nof_detected_prach))
|
&nof_detected_prach))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error detecting PRACH\n");
|
fprintf(stderr, "Error detecting PRACH\n");
|
||||||
|
|
|
@ -50,7 +50,7 @@ int srslte_mod_modulate(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, u
|
||||||
}
|
}
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mod_bpsk_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) {
|
void mod_bpsk_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) {
|
||||||
uint8_t mask_bpsk[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
uint8_t mask_bpsk[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||||
uint8_t shift_bpsk[8] = {7, 6, 5, 4, 3, 2, 1, 0};
|
uint8_t shift_bpsk[8] = {7, 6, 5, 4, 3, 2, 1, 0};
|
||||||
|
|
|
@ -292,8 +292,10 @@ void srslte_pbch_mib_unpack(uint8_t *msg, srslte_cell_t *cell, uint32_t *sfn) {
|
||||||
/** Unpacks MIB from PBCH message.
|
/** Unpacks MIB from PBCH message.
|
||||||
* msg buffer must be 24 byte length at least
|
* msg buffer must be 24 byte length at least
|
||||||
*/
|
*/
|
||||||
void srslte_pbch_mib_pack(srslte_cell_t *cell, uint32_t sfn, uint8_t *msg) {
|
void srslte_pbch_mib_pack(srslte_cell_t *cell, uint32_t sfn, uint8_t *payload) {
|
||||||
int bw, phich_res = 0;
|
int bw, phich_res = 0;
|
||||||
|
|
||||||
|
uint8_t *msg = payload;
|
||||||
|
|
||||||
bzero(msg, 24);
|
bzero(msg, 24);
|
||||||
|
|
||||||
|
@ -325,6 +327,7 @@ void srslte_pbch_mib_pack(srslte_cell_t *cell, uint32_t sfn, uint8_t *msg) {
|
||||||
}
|
}
|
||||||
srslte_bit_unpack(phich_res, &msg, 2);
|
srslte_bit_unpack(phich_res, &msg, 2);
|
||||||
srslte_bit_unpack(sfn >> 2, &msg, 8);
|
srslte_bit_unpack(sfn >> 2, &msg, 8);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_pbch_decode_reset(srslte_pbch_t *q) {
|
void srslte_pbch_decode_reset(srslte_pbch_t *q) {
|
||||||
|
|
|
@ -32,10 +32,10 @@
|
||||||
#include "srslte/utils/debug.h"
|
#include "srslte/utils/debug.h"
|
||||||
#include "srslte/utils/vector.h"
|
#include "srslte/utils/vector.h"
|
||||||
|
|
||||||
|
float save_corr[4096];
|
||||||
|
|
||||||
//PRACH detection threshold is PRACH_DETECT_FACTOR*average
|
//PRACH detection threshold is PRACH_DETECT_FACTOR*average
|
||||||
#define PRACH_DETECT_FACTOR 18
|
#define PRACH_DETECT_FACTOR 18
|
||||||
#define CFO_REPLICA_FACTOR 0.3
|
|
||||||
|
|
||||||
#define N_SEQS 64 // Number of prach sequences available
|
#define N_SEQS 64 // Number of prach sequences available
|
||||||
#define N_RB_SC 12 // Number of subcarriers per resource block
|
#define N_RB_SC 12 // Number of subcarriers per resource block
|
||||||
|
@ -440,8 +440,9 @@ int srslte_prach_init(srslte_prach_t *p,
|
||||||
srslte_dft_plan_set_norm(p->fft, false);
|
srslte_dft_plan_set_norm(p->fft, false);
|
||||||
|
|
||||||
p->N_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048;
|
p->N_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048;
|
||||||
p->N_cp = prach_Tcp[p->f]*p->N_ifft_ul/2048;
|
p->N_cp = prach_Tcp[p->f]*p->N_ifft_ul/2048;
|
||||||
|
p->T_seq = prach_Tseq[p->f]*SRSLTE_LTE_TS;
|
||||||
|
|
||||||
ret = SRSLTE_SUCCESS;
|
ret = SRSLTE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invalid parameters\n");
|
fprintf(stderr, "Invalid parameters\n");
|
||||||
|
@ -506,7 +507,7 @@ int srslte_prach_detect(srslte_prach_t *p,
|
||||||
uint32_t *indices,
|
uint32_t *indices,
|
||||||
uint32_t *n_indices)
|
uint32_t *n_indices)
|
||||||
{
|
{
|
||||||
return srslte_prach_detect_offset(p, freq_offset, signal, sig_len, indices, NULL, n_indices);
|
return srslte_prach_detect_offset(p, freq_offset, signal, sig_len, indices, NULL, NULL, n_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
int srslte_prach_detect_offset(srslte_prach_t *p,
|
int srslte_prach_detect_offset(srslte_prach_t *p,
|
||||||
|
@ -514,7 +515,8 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
|
||||||
cf_t *signal,
|
cf_t *signal,
|
||||||
uint32_t sig_len,
|
uint32_t sig_len,
|
||||||
uint32_t *indices,
|
uint32_t *indices,
|
||||||
uint32_t *offsets,
|
float *t_offsets,
|
||||||
|
float *peak_to_avg,
|
||||||
uint32_t *n_indices)
|
uint32_t *n_indices)
|
||||||
{
|
{
|
||||||
int ret = SRSLTE_ERROR;
|
int ret = SRSLTE_ERROR;
|
||||||
|
@ -525,7 +527,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
|
||||||
{
|
{
|
||||||
|
|
||||||
if(sig_len < p->N_ifft_prach){
|
if(sig_len < p->N_ifft_prach){
|
||||||
fprintf(stderr, "srslte_prach_detect: Signal is not of length %d", p->N_ifft_prach);
|
fprintf(stderr, "srslte_prach_detect: Signal length is %d and should be %d\n", sig_len, p->N_ifft_prach);
|
||||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +564,6 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
|
||||||
uint32_t n_wins = p->N_zc/winsize;
|
uint32_t n_wins = p->N_zc/winsize;
|
||||||
|
|
||||||
float max_peak = 0;
|
float max_peak = 0;
|
||||||
|
|
||||||
for(int j=0;j<n_wins;j++) {
|
for(int j=0;j<n_wins;j++) {
|
||||||
uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc;
|
uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc;
|
||||||
uint32_t end = start+winsize;
|
uint32_t end = start+winsize;
|
||||||
|
@ -583,12 +584,20 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
|
||||||
}
|
}
|
||||||
if (max_peak > p->detect_factor*corr_ave) {
|
if (max_peak > p->detect_factor*corr_ave) {
|
||||||
for (int j=0;j<n_wins;j++) {
|
for (int j=0;j<n_wins;j++) {
|
||||||
if(p->peak_values[j] > p->detect_factor*corr_ave &&
|
if(p->peak_values[j] > p->detect_factor*corr_ave)
|
||||||
p->peak_values[j] >= CFO_REPLICA_FACTOR*max_peak)
|
|
||||||
{
|
{
|
||||||
indices[*n_indices] = (i*n_wins)+j;
|
printf("ncs=%d, nzc=%d, nwins=%d, Nroot=%d, i=%d, j=%d, start=%d, peak_value=%f, peak_offset=%d, tseq=%f\n",
|
||||||
if (offsets) {
|
p->N_cs, p->N_zc, n_wins, p->N_roots, i, j, (p->N_zc-(j*p->N_cs))%p->N_zc, p->peak_values[j],
|
||||||
offsets[*n_indices] = p->peak_offsets[j];
|
p->peak_offsets[j], p->T_seq*1e6);
|
||||||
|
memcpy(save_corr, p->corr, p->N_zc*sizeof(float));
|
||||||
|
if (indices) {
|
||||||
|
indices[*n_indices] = (i*n_wins)+j;
|
||||||
|
}
|
||||||
|
if (peak_to_avg) {
|
||||||
|
peak_to_avg[*n_indices] = p->peak_values[j]/corr_ave;
|
||||||
|
}
|
||||||
|
if (t_offsets) {
|
||||||
|
t_offsets[*n_indices] = (float) p->peak_offsets[j]*p->T_seq/p->N_zc;
|
||||||
}
|
}
|
||||||
(*n_indices)++;
|
(*n_indices)++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include "srslte/srslte.h"
|
#include "srslte/srslte.h"
|
||||||
#include "srslte/mex/mexutils.h"
|
#include "srslte/mex/mexutils.h"
|
||||||
|
|
||||||
|
extern float save_corr[4096];
|
||||||
|
|
||||||
/** MEX function to be called from MATLAB to test the channel estimator
|
/** MEX function to be called from MATLAB to test the channel estimator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -85,7 +87,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
mexutils_read_uint32_struct(PRACHCFG, "FreqOffset", &frequency_offset);
|
mexutils_read_uint32_struct(PRACHCFG, "FreqOffset", &frequency_offset);
|
||||||
|
|
||||||
srslte_prach_t prach;
|
srslte_prach_t prach;
|
||||||
if (srslte_prach_init(&prach, N_ifft_ul, preamble_format, root_seq_idx, high_speed_flag, zero_corr_zone)) {
|
if (srslte_prach_init(&prach, N_ifft_ul, preamble_format*16, root_seq_idx, high_speed_flag, zero_corr_zone)) {
|
||||||
mexErrMsgTxt("Error initiating PRACH\n");
|
mexErrMsgTxt("Error initiating PRACH\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +96,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
int nof_samples = mexutils_read_cf(INPUT, &input_signal);
|
int nof_samples = mexutils_read_cf(INPUT, &input_signal);
|
||||||
|
|
||||||
uint32_t preambles[64];
|
uint32_t preambles[64];
|
||||||
uint32_t offsets[64];
|
float offsets[64];
|
||||||
uint32_t nof_detected = 0;
|
uint32_t nof_detected = 0;
|
||||||
|
|
||||||
if (nrhs > NOF_INPUTS) {
|
if (nrhs > NOF_INPUTS) {
|
||||||
|
@ -102,7 +104,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
srslte_prach_set_detect_factor(&prach, factor);
|
srslte_prach_set_detect_factor(&prach, factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srslte_prach_detect_offset(&prach, frequency_offset, &input_signal[prach.N_cp], nof_samples, preambles, offsets, &nof_detected)) {
|
if (srslte_prach_detect_offset(&prach, frequency_offset, &input_signal[prach.N_cp], nof_samples, preambles, offsets, NULL, &nof_detected)) {
|
||||||
mexErrMsgTxt("Error detecting PRACH\n");
|
mexErrMsgTxt("Error detecting PRACH\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +113,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
mexutils_write_int((int*) preambles, &plhs[0], nof_detected, 1);
|
mexutils_write_int((int*) preambles, &plhs[0], nof_detected, 1);
|
||||||
}
|
}
|
||||||
if (nlhs >= 2) {
|
if (nlhs >= 2) {
|
||||||
mexutils_write_int((int*) offsets, &plhs[1], nof_detected, 1);
|
mexutils_write_f(offsets, &plhs[1], nof_detected, 1);
|
||||||
|
}
|
||||||
|
if (nlhs >= 3) {
|
||||||
|
mexutils_write_f(save_corr, &plhs[2], prach.N_zc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(input_signal);
|
free(input_signal);
|
||||||
|
|
|
@ -82,7 +82,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
mexutils_read_uint32_struct(PRACHCFG, "FreqOffset", &frequency_offset);
|
mexutils_read_uint32_struct(PRACHCFG, "FreqOffset", &frequency_offset);
|
||||||
|
|
||||||
srslte_prach_t prach;
|
srslte_prach_t prach;
|
||||||
if (srslte_prach_init(&prach, N_ifft_ul, preamble_format, root_seq_idx, high_speed_flag, zero_corr_zone)) {
|
if (srslte_prach_init(&prach, N_ifft_ul, preamble_format*16, root_seq_idx, high_speed_flag, zero_corr_zone)) {
|
||||||
mexErrMsgTxt("Error initiating PRACH\n");
|
mexErrMsgTxt("Error initiating PRACH\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,13 @@ uint32_t preamble_format = 0;
|
||||||
uint32_t root_seq_idx = 0;
|
uint32_t root_seq_idx = 0;
|
||||||
uint32_t seq_idx = 0;
|
uint32_t seq_idx = 0;
|
||||||
uint32_t frequency_offset = 0;
|
uint32_t frequency_offset = 0;
|
||||||
uint32_t zero_corr_zone = 0;
|
uint32_t zero_corr_zone = 11;
|
||||||
|
uint32_t timeadv = 0;
|
||||||
uint32_t nof_frames = 20;
|
uint32_t nof_frames = 20;
|
||||||
|
|
||||||
float uhd_gain=40, uhd_freq=2.4e9;
|
float uhd_gain=40, uhd_freq=2.4e9;
|
||||||
char *uhd_args="";
|
char *uhd_args="";
|
||||||
char *output_filename = NULL;
|
char *output_filename = "prach_rx";
|
||||||
|
|
||||||
void usage(char *prog) {
|
void usage(char *prog) {
|
||||||
printf("Usage: %s \n", prog);
|
printf("Usage: %s \n", prog);
|
||||||
|
@ -58,15 +59,17 @@ void usage(char *prog) {
|
||||||
printf("\t-g UHD TX/RX gain [Default %.1f dB]\n", uhd_gain);
|
printf("\t-g UHD TX/RX gain [Default %.1f dB]\n", uhd_gain);
|
||||||
printf("\t-p Number of UL RB [Default %d]\n", nof_prb);
|
printf("\t-p Number of UL RB [Default %d]\n", nof_prb);
|
||||||
printf("\t-F Preamble format [Default %d]\n", preamble_format);
|
printf("\t-F Preamble format [Default %d]\n", preamble_format);
|
||||||
|
printf("\t-O Frequency offset [Default %d]\n", frequency_offset);
|
||||||
printf("\t-s sequence index [Default %d]\n", seq_idx);
|
printf("\t-s sequence index [Default %d]\n", seq_idx);
|
||||||
printf("\t-r Root sequence index [Default %d]\n", root_seq_idx);
|
printf("\t-r Root sequence index [Default %d]\n", root_seq_idx);
|
||||||
|
printf("\t-t Time advance (us) [Default %d]\n", timeadv);
|
||||||
printf("\t-z Zero correlation zone config [Default %d]\n", zero_corr_zone);
|
printf("\t-z Zero correlation zone config [Default %d]\n", zero_corr_zone);
|
||||||
printf("\t-o Save transmitted PRACH in file [Default no]\n");
|
printf("\t-o Save transmitted PRACH in file [Default no]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_args(int argc, char **argv) {
|
void parse_args(int argc, char **argv) {
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "apfFgrsoz")) != -1) {
|
while ((opt = getopt(argc, argv, "apfFgrstoPOz")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
case 'a':
|
||||||
uhd_args = argv[optind];
|
uhd_args = argv[optind];
|
||||||
|
@ -80,6 +83,15 @@ void parse_args(int argc, char **argv) {
|
||||||
case 'g':
|
case 'g':
|
||||||
uhd_gain = atof(argv[optind]);
|
uhd_gain = atof(argv[optind]);
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
preamble_format = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
frequency_offset = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
timeadv = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
nof_prb = atoi(argv[optind]);
|
nof_prb = atoi(argv[optind]);
|
||||||
if (!srslte_nofprb_isvalid(nof_prb)) {
|
if (!srslte_nofprb_isvalid(nof_prb)) {
|
||||||
|
@ -123,7 +135,8 @@ int main(int argc, char **argv) {
|
||||||
high_speed_flag,
|
high_speed_flag,
|
||||||
zero_corr_zone);
|
zero_corr_zone);
|
||||||
|
|
||||||
uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000;
|
int srate = srslte_sampling_freq_hz(nof_prb);
|
||||||
|
uint32_t flen = srate/1000;
|
||||||
|
|
||||||
printf("Generating PRACH\n");
|
printf("Generating PRACH\n");
|
||||||
bzero(preamble, flen*sizeof(cf_t));
|
bzero(preamble, flen*sizeof(cf_t));
|
||||||
|
@ -133,7 +146,7 @@ int main(int argc, char **argv) {
|
||||||
preamble);
|
preamble);
|
||||||
|
|
||||||
|
|
||||||
uint32_t prach_len = p->N_seq;
|
uint32_t prach_len = p->N_seq+p->N_cp;
|
||||||
|
|
||||||
srslte_vec_save_file("generated",preamble,prach_len*sizeof(cf_t));
|
srslte_vec_save_file("generated",preamble,prach_len*sizeof(cf_t));
|
||||||
|
|
||||||
|
@ -147,11 +160,27 @@ int main(int argc, char **argv) {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
printf("Subframe len: %d samples\n", flen);
|
printf("Subframe len: %d samples\n", flen);
|
||||||
printf("Set TX/RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000);
|
printf("Set RX gain: %.1f dB\n", uhd_gain);
|
||||||
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&uhd, uhd_gain));
|
printf("Set TX gain: %.1f dB\n", 20+uhd_gain);
|
||||||
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&uhd, uhd_gain));
|
printf("Set TX/RX freq: %.2f MHz\n", uhd_freq/ 1000000);
|
||||||
printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&uhd, uhd_freq) / 1000000);
|
|
||||||
srslte_rf_set_tx_srate(&uhd, srslte_sampling_freq_hz(nof_prb));
|
srslte_rf_set_rx_gain(&uhd, uhd_gain);
|
||||||
|
srslte_rf_set_tx_gain(&uhd, 10+uhd_gain);
|
||||||
|
srslte_rf_set_rx_freq(&uhd, uhd_freq);
|
||||||
|
srslte_rf_set_tx_freq(&uhd, uhd_freq);
|
||||||
|
|
||||||
|
if (srate < 10e6) {
|
||||||
|
srslte_rf_set_master_clock_rate(&uhd, 4*srate);
|
||||||
|
} else {
|
||||||
|
srslte_rf_set_master_clock_rate(&uhd, srate);
|
||||||
|
}
|
||||||
|
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
|
||||||
|
float srate_rf = srslte_rf_set_rx_srate(&uhd, (double) srate);
|
||||||
|
if (srate_rf != srate) {
|
||||||
|
fprintf(stderr, "Could not set sampling rate\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
srslte_rf_set_tx_srate(&uhd, (double) srate);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
cf_t *zeros = calloc(sizeof(cf_t),flen);
|
cf_t *zeros = calloc(sizeof(cf_t),flen);
|
||||||
|
@ -171,7 +200,7 @@ int main(int argc, char **argv) {
|
||||||
srslte_rf_recv_with_time(&uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
|
srslte_rf_recv_with_time(&uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
|
||||||
nframe++;
|
nframe++;
|
||||||
if (nframe==9 || nframe==8) {
|
if (nframe==9 || nframe==8) {
|
||||||
srslte_timestamp_add(&tstamp, 0, 2e-3);
|
srslte_timestamp_add(&tstamp, 0, 2e-3-timeadv*1e-6);
|
||||||
if (nframe==8) {
|
if (nframe==8) {
|
||||||
srslte_rf_send_timed2(&uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
|
srslte_rf_send_timed2(&uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
|
||||||
printf("Transmitting zeros\n");
|
printf("Transmitting zeros\n");
|
||||||
|
@ -183,7 +212,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
}
|
}
|
||||||
if (f) {
|
if (f) {
|
||||||
fwrite(&buffer[10*flen], flen*sizeof(cf_t), 1, f);
|
fwrite(buffer, 11*flen*sizeof(cf_t), 1, f);
|
||||||
}
|
}
|
||||||
if (f) {
|
if (f) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
Loading…
Reference in New Issue