Added frequency shift to fft to support SC-FDMA

master
ismagom 10 years ago
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…
Cancel
Save