Improvements in prach detection

This commit is contained in:
Ismael Gomez 2016-07-27 16:44:14 +02:00
parent 9618135423
commit cc00b172b5
13 changed files with 124 additions and 61 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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;
} }

View File

@ -84,6 +84,8 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
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");
goto clean_exit; goto clean_exit;
@ -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");

View File

@ -292,9 +292,11 @@ 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);
if (cell->nof_prb <= 6) { if (cell->nof_prb <= 6) {
@ -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) {

View File

@ -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
@ -441,6 +441,7 @@ int srslte_prach_init(srslte_prach_t *p,
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 {
@ -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)
{ {
printf("ncs=%d, nzc=%d, nwins=%d, Nroot=%d, i=%d, j=%d, start=%d, peak_value=%f, peak_offset=%d, tseq=%f\n",
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],
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; indices[*n_indices] = (i*n_wins)+j;
if (offsets) { }
offsets[*n_indices] = p->peak_offsets[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)++;
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);