mirror of https://github.com/PentHertz/srsLTE.git
Added frequency shift to fft to support SC-FDMA
This commit is contained in:
parent
861d4b3985
commit
31a4edffae
|
@ -37,7 +37,7 @@
|
|||
#include "liblte/phy/common/phy_common.h"
|
||||
#include "liblte/phy/utils/dft.h"
|
||||
|
||||
//#define LTE_FFT_NORMALIZE
|
||||
#define LTE_FFT_NORMALIZE
|
||||
|
||||
typedef _Complex float cf_t; /* this is only a shortcut */
|
||||
|
||||
|
@ -51,6 +51,9 @@ typedef struct LIBLTE_API{
|
|||
uint32_t slot_sz;
|
||||
lte_cp_t cp;
|
||||
cf_t *tmp; // for removing zero padding
|
||||
|
||||
bool freq_shift;
|
||||
cf_t *shift_buffer;
|
||||
}lte_fft_t;
|
||||
|
||||
LIBLTE_API int lte_fft_init(lte_fft_t *q,
|
||||
|
@ -81,4 +84,7 @@ LIBLTE_API void lte_ifft_run_sf(lte_fft_t *q,
|
|||
cf_t *input,
|
||||
cf_t *output);
|
||||
|
||||
LIBLTE_API int lte_fft_set_freq_shift(lte_fft_t *q,
|
||||
float freq_shift);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "liblte/phy/common/phy_common.h"
|
||||
#include "liblte/phy/utils/dft.h"
|
||||
|
@ -54,13 +56,11 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp, uint32_t nof_prb, dft_dir_t dir) {
|
|||
|
||||
dft_plan_set_mirror(&q->fft_plan, true);
|
||||
dft_plan_set_dc(&q->fft_plan, true);
|
||||
#ifdef LTE_FFT_NORMALIZE
|
||||
dft_plan_set_norm(&q->fft_plan, true);
|
||||
#endif
|
||||
|
||||
q->symbol_sz = (uint32_t) symbol_sz;
|
||||
q->nof_symbols = CP_NSYMB(cp);
|
||||
q->cp = cp;
|
||||
q->freq_shift = false;
|
||||
q->nof_re = nof_prb * RE_X_RB;
|
||||
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
|
||||
q->slot_sz = SLOT_LEN(symbol_sz);
|
||||
|
@ -77,6 +77,9 @@ void lte_fft_free_(lte_fft_t *q) {
|
|||
if (q->tmp) {
|
||||
free(q->tmp);
|
||||
}
|
||||
if (q->shift_buffer) {
|
||||
free(q->shift_buffer);
|
||||
}
|
||||
bzero(q, sizeof(lte_fft_t));
|
||||
}
|
||||
|
||||
|
@ -106,6 +109,35 @@ int lte_ifft_init(lte_fft_t *q, lte_cp_t cp, uint32_t nof_prb) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Shifts the signal after the iFFT or before the FFT.
|
||||
* Freq_shift is relative to inter-carrier spacing.
|
||||
* Caution: This function shall not be called during run-time
|
||||
*/
|
||||
int lte_fft_set_freq_shift(lte_fft_t *q, float freq_shift) {
|
||||
q->shift_buffer = vec_malloc(sizeof(cf_t) * SF_LEN(q->symbol_sz));
|
||||
if (!q->shift_buffer) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
cf_t *ptr = q->shift_buffer;
|
||||
for (uint32_t n=0;n<2;n++) {
|
||||
for (uint32_t i=0;i<q->nof_symbols;i++) {
|
||||
uint32_t cplen = CP_ISNORM(q->cp)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz);
|
||||
for (uint32_t t=0;t<q->symbol_sz+cplen;t++) {
|
||||
ptr[t] = cexpf(I*2*M_PI*((float) t-(float)cplen)*freq_shift/q->symbol_sz);
|
||||
}
|
||||
ptr += q->symbol_sz+cplen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable DC carrier addition */
|
||||
dft_plan_set_dc(&q->fft_plan, false);
|
||||
|
||||
q->freq_shift = true;
|
||||
|
||||
return LIBLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void lte_ifft_free(lte_fft_t *q) {
|
||||
lte_fft_free_(q);
|
||||
}
|
||||
|
@ -126,6 +158,9 @@ void lte_fft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) {
|
|||
|
||||
void lte_fft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) {
|
||||
uint32_t n;
|
||||
if (q->freq_shift) {
|
||||
vec_prod_ccc(input, q->shift_buffer, input, 2*q->slot_sz);
|
||||
}
|
||||
for (n=0;n<2;n++) {
|
||||
lte_fft_run_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]);
|
||||
}
|
||||
|
@ -152,4 +187,10 @@ void lte_ifft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) {
|
|||
for (n=0;n<2;n++) {
|
||||
lte_ifft_run_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]);
|
||||
}
|
||||
if (q->freq_shift) {
|
||||
vec_prod_ccc(output, q->shift_buffer, output, 2*q->slot_sz);
|
||||
}
|
||||
#ifdef LTE_FFT_NORMALIZE
|
||||
vec_sc_prod_cfc(output, (float) 1.0/sqrtf(q->symbol_sz),output,2*q->slot_sz);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -192,17 +192,28 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cf_t *scfdma = vec_malloc(sizeof(cf_t) * SF_LEN_PRB(cell.nof_prb));
|
||||
bzero(scfdma, sizeof(cf_t) * SF_LEN_PRB(cell.nof_prb));
|
||||
lte_fft_t fft;
|
||||
lte_ifft_init(&fft, CPNORM, cell.nof_prb);
|
||||
lte_fft_set_freq_shift(&fft, 0.5);
|
||||
lte_ifft_run_sf(&fft, sf_symbols, scfdma);
|
||||
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(sf_symbols, &plhs[0], nof_re, 1);
|
||||
mexutils_write_cf(scfdma, &plhs[0], SF_LEN_PRB(cell.nof_prb), 1);
|
||||
}
|
||||
if (nlhs >= 2) {
|
||||
mexutils_write_cf(pusch.pusch_z, &plhs[1], harq_process.nof_re, 1);
|
||||
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
|
||||
}
|
||||
if (nlhs >= 3) {
|
||||
mexutils_write_cf(pusch.pusch_z, &plhs[2], harq_process.nof_re, 1);
|
||||
}
|
||||
pusch_free(&pusch);
|
||||
free(trblkin);
|
||||
free(uci_data.uci_cqi);
|
||||
free(sf_symbols);
|
||||
free(scfdma);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -230,6 +230,14 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
cf_t *scfdma = vec_malloc(sizeof(cf_t) * SF_LEN_PRB(cell.nof_prb));
|
||||
bzero(scfdma, sizeof(cf_t) * SF_LEN_PRB(cell.nof_prb));
|
||||
lte_fft_t fft;
|
||||
lte_ifft_init(&fft, CPNORM, cell.nof_prb);
|
||||
lte_fft_set_freq_shift(&fft, 0.5);
|
||||
lte_ifft_run_sf(&fft, sf_symbols, scfdma);
|
||||
|
||||
gettimeofday(&t[1], NULL);
|
||||
//int r = pusch_decode(&pusch, slot_symbols[0], ce, 0, data, subframe, &harq_process, rv);
|
||||
int r = 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
clear
|
||||
ueConfig=struct('NCellID',3,'NULRB',6,'NSubframe',0,'RNTI',1,'CyclicPrefixUL','Normal','NTxAnts',1);
|
||||
ueConfig=struct('NCellID',3,'NULRB',25,'NSubframe',0,'RNTI',1,'CyclicPrefixUL','Normal','NTxAnts',1);
|
||||
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[0 1]','Modulation','QPSK','RV',0,'Shortened',0);
|
||||
|
||||
addpath('../../debug/lte/phy/lib/phch/test')
|
||||
|
@ -43,8 +43,10 @@ for i=1:length(TBs)
|
|||
idx=ltePUSCHIndices(ueConfig,puschConfig);
|
||||
subframe_mat = lteULResourceGrid(ueConfig);
|
||||
subframe_mat(idx)=cw_mat;
|
||||
[subframe_lib, cwlib]=liblte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
|
||||
err=mean(abs(subframe_mat(:)-subframe_lib));
|
||||
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
|
||||
|
||||
[waveform_lib, subframe_lib, cwlib]=liblte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
|
||||
err=mean(abs(waveform-waveform_lib));
|
||||
if (err > 10^-6)
|
||||
disp(err)
|
||||
error('Error!');
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
clear
|
||||
ue = struct('NULRB',6,'NDLRB',6);
|
||||
d = lteULResourceGridSize(ue);
|
||||
rgrid = complex(rand(d)-0.5,rand(d)-0.5);
|
||||
waveform = lteSCFDMAModulate(ue,rgrid,0);
|
||||
|
||||
wave = [];
|
||||
freq_correct=[];
|
||||
for i=1:14
|
||||
symbol = ifft(ifftshift([zeros(28,1); rgrid(:,i); zeros(28,1)]),128);
|
||||
if (i==1 || i==8)
|
||||
cp_len=10;
|
||||
else
|
||||
cp_len=9;
|
||||
end
|
||||
symbol_cp=[symbol((128-cp_len+1):128); symbol(1:128)];
|
||||
freq_correct=[freq_correct; exp(1i*pi*(-cp_len:127)'/128)];
|
||||
wave = [wave; symbol_cp];
|
||||
end
|
||||
|
||||
wave=wave.*freq_correct;
|
||||
|
||||
%wave=transpose(wave);
|
||||
%plot(1:138,fftshift(fft(waveform(1:138))),1:138,fftshift(fft(wave(1:138))))
|
||||
plot(abs(wave(1:138)-waveform(1:138)))
|
||||
mean(abs(wave-waveform))
|
Loading…
Reference in New Issue