Skip to content

Commit 03724f3

Browse files
authored
Merge pull request #21 from tejeez/master
Support for receivers providing real signal
2 parents 47333b6 + b6f50cb commit 03724f3

6 files changed

Lines changed: 174 additions & 0 deletions

File tree

csdr.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,55 @@ int main(int argc, char *argv[])
836836
return 0;
837837
}
838838

839+
if(!strcmp(argv[1],"shift_addition_fc"))
840+
{
841+
bigbufs=1;
842+
843+
float starting_phase=0;
844+
float rate;
845+
846+
int fd;
847+
if(fd=init_fifo(argc,argv))
848+
{
849+
while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000);
850+
}
851+
else
852+
{
853+
if(argc<=2) return badsyntax("need required parameter (rate)");
854+
sscanf(argv[2],"%g",&rate);
855+
}
856+
857+
if(!sendbufsize(initialize_buffers())) return -2;
858+
for(;;)
859+
{
860+
shift_addition_data_t data=shift_addition_init(rate);
861+
fprintf(stderr,"shift_addition_fc: reinitialized to %g\n",rate);
862+
int remain, current_size;
863+
float* ibufptr;
864+
float* obufptr;
865+
for(;;)
866+
{
867+
FEOF_CHECK;
868+
if(!FREAD_R) break;
869+
remain=the_bufsize;
870+
ibufptr=input_buffer;
871+
obufptr=output_buffer;
872+
while(remain)
873+
{
874+
current_size=(remain>1024)?1024:remain;
875+
starting_phase=shift_addition_fc(ibufptr, (complexf*)obufptr, current_size, data, starting_phase);
876+
ibufptr+=current_size;
877+
obufptr+=current_size*2;
878+
remain-=current_size;
879+
}
880+
FWRITE_C;
881+
if(read_fifo_ctl(fd,"%g\n",&rate)) break;
882+
TRY_YIELD;
883+
}
884+
}
885+
return 0;
886+
}
887+
839888
if(!strcmp(argv[1],"shift_addition_cc_test"))
840889
{
841890
if(argc<=2) return badsyntax("need required parameter (rate)");
@@ -1495,6 +1544,94 @@ int main(int argc, char *argv[])
14951544
TRY_YIELD;
14961545
}
14971546
}
1547+
1548+
if(!strcmp(argv[1],"fft_fc"))
1549+
{
1550+
/*
1551+
For real FFT, the parameter is the number of output complex bins
1552+
instead of the actual FFT size.
1553+
Number of input samples used for each FFT is twice the given parameter.
1554+
This makes it easier to replace fft_cc by fft_fc in some applications. */
1555+
if(argc<=3) return badsyntax("need required parameters (fft_out_size, out_of_every_n_samples)");
1556+
int fft_in_size=0, fft_out_size=0;
1557+
sscanf(argv[2],"%d",&fft_out_size);
1558+
if(log2n(fft_out_size)==-1) return badsyntax("fft_out_size should be power of 2");
1559+
fft_in_size = 2*fft_out_size;
1560+
int every_n_samples;
1561+
sscanf(argv[3],"%d",&every_n_samples);
1562+
int benchmark=0;
1563+
int octave=0;
1564+
window_t window = WINDOW_DEFAULT;
1565+
if(argc>=5)
1566+
{
1567+
window=firdes_get_window_from_string(argv[4]);
1568+
}
1569+
if(argc>=6)
1570+
{
1571+
benchmark|=!strcmp("--benchmark",argv[5]);
1572+
octave|=!strcmp("--octave",argv[5]);
1573+
}
1574+
if(argc>=7)
1575+
{
1576+
benchmark|=!strcmp("--benchmark",argv[6]);
1577+
octave|=!strcmp("--octave",argv[6]);
1578+
}
1579+
1580+
if(!initialize_buffers()) return -2;
1581+
sendbufsize(fft_out_size);
1582+
1583+
//make FFT plan
1584+
float* input=(float*)fft_malloc(sizeof(float)*fft_in_size);
1585+
float* windowed=(float*)fft_malloc(sizeof(float)*fft_in_size);
1586+
complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_out_size);
1587+
if(benchmark) fprintf(stderr,"fft_cc: benchmarking...");
1588+
FFT_PLAN_T* plan=make_fft_r2c(fft_in_size, windowed, output, benchmark);
1589+
if(benchmark) fprintf(stderr," done\n");
1590+
//if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); // TODO
1591+
float *windowt;
1592+
windowt = precalculate_window(fft_in_size, window);
1593+
for(;;)
1594+
{
1595+
FEOF_CHECK;
1596+
if(every_n_samples>fft_in_size)
1597+
{
1598+
fread(input, sizeof(float), fft_in_size, stdin);
1599+
//skipping samples before next FFT (but fseek doesn't work for pipes)
1600+
for(int seek_remain=every_n_samples-fft_in_size;seek_remain>0;seek_remain-=the_bufsize)
1601+
{
1602+
fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin);
1603+
}
1604+
}
1605+
else
1606+
{
1607+
//overlapped FFT
1608+
for(int i=0;i<fft_in_size-every_n_samples;i++) input[i]=input[i+every_n_samples];
1609+
fread(input+fft_in_size-every_n_samples, sizeof(float), every_n_samples, stdin);
1610+
}
1611+
//apply_window_c(input,windowed,fft_size,window);
1612+
apply_precalculated_window_f(input,windowed,fft_in_size,windowt);
1613+
fft_execute(plan);
1614+
if(octave)
1615+
{
1616+
#if 0
1617+
// TODO
1618+
printf("fftdata=[");
1619+
//we have to swap the two parts of the array to get a valid spectrum
1620+
for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
1621+
for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
1622+
printf(
1623+
"];\n"
1624+
"y=abs(fftdata);\n"
1625+
"refreshdata;\n"
1626+
);
1627+
#endif
1628+
}
1629+
else fwrite(output, sizeof(complexf), fft_out_size, stdout);
1630+
TRY_YIELD;
1631+
}
1632+
}
1633+
1634+
14981635
#define LOGPOWERCF_BUFSIZE 64
14991636
if(!strcmp(argv[1],"logpower_cf"))
15001637
{

fft_fftw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct fft_plan_s
2222
#include "libcsdr.h"
2323

2424
FFT_PLAN_T* make_fft_c2c(int size, complexf* input, complexf* output, int forward, int benchmark);
25+
FFT_PLAN_T* make_fft_r2c(int size, float* input, complexf* output, int benchmark);
2526
void fft_execute(FFT_PLAN_T* plan);
2627
void fft_destroy(FFT_PLAN_T* plan);
2728

libcsdr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,13 @@ void apply_precalculated_window_c(complexf* input, complexf* output, int size, f
12461246
}
12471247
}
12481248

1249+
void apply_precalculated_window_f(float* input, float* output, int size, float *windowt)
1250+
{
1251+
for(int i=0;i<size;i++) //@apply_precalculated_window_f
1252+
{
1253+
output[i] = input[i] * windowt[i];
1254+
}
1255+
}
12491256

12501257
void apply_window_f(float* input, float* output, int size, window_t window)
12511258
{

libcsdr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ void rational_resampler_get_lowpass_f(float* output, int output_size, int interp
140140
float *precalculate_window(int size, window_t window);
141141
void apply_window_c(complexf* input, complexf* output, int size, window_t window);
142142
void apply_precalculated_window_c(complexf* input, complexf* output, int size, float *windowt);
143+
void apply_precalculated_window_f(float* input, float* output, int size, float *windowt);
143144
void apply_window_f(float* input, float* output, int size, window_t window);
144145
void logpower_cf(complexf* input, float* output, int size, float add_db);
145146
void accumulate_power_cf(complexf* input, float* output, int size);

libcsdr_gpl.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,33 @@ float shift_addition_cc(complexf *input, complexf* output, int input_size, shift
5151
return starting_phase;
5252
}
5353

54+
float shift_addition_fc(float *input, complexf* output, int input_size, shift_addition_data_t d, float starting_phase)
55+
{
56+
//The original idea was taken from wdsp:
57+
//http://svn.tapr.org/repos_sdr_hpsdr/trunk/W5WC/PowerSDR_HPSDR_mRX_PS/Source/wdsp/shift.c
58+
59+
//However, this method introduces noise (from floating point rounding errors), which increases until the end of the buffer.
60+
//fprintf(stderr, "cosd=%g sind=%g\n", d.cosdelta, d.sindelta);
61+
float cosphi=cos(starting_phase);
62+
float sinphi=sin(starting_phase);
63+
float cosphi_last, sinphi_last;
64+
for(int i=0;i<input_size;i++) //@shift_addition_cc: work
65+
{
66+
iof(output,i)=cosphi*input[i];
67+
qof(output,i)=sinphi*input[i];
68+
//using the trigonometric addition formulas
69+
//cos(phi+delta)=cos(phi)cos(delta)-sin(phi)*sin(delta)
70+
cosphi_last=cosphi;
71+
sinphi_last=sinphi;
72+
cosphi=cosphi_last*d.cosdelta-sinphi_last*d.sindelta;
73+
sinphi=sinphi_last*d.cosdelta+cosphi_last*d.sindelta;
74+
}
75+
starting_phase+=d.rate*PI*input_size;
76+
while(starting_phase>PI) starting_phase-=2*PI; //@shift_addition_cc: normalize starting_phase
77+
while(starting_phase<-PI) starting_phase+=2*PI;
78+
return starting_phase;
79+
}
80+
5481
shift_addition_data_t shift_addition_init(float rate)
5582
{
5683
rate*=2;

libcsdr_gpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef struct shift_addition_data_s
3131
} shift_addition_data_t;
3232
shift_addition_data_t shift_addition_init(float rate);
3333
float shift_addition_cc(complexf *input, complexf* output, int input_size, shift_addition_data_t d, float starting_phase);
34+
float shift_addition_fc(float *input, complexf* output, int input_size, shift_addition_data_t d, float starting_phase);
3435
void shift_addition_cc_test(shift_addition_data_t d);
3536

3637
float agc_ff(float* input, float* output, int input_size, float reference, float attack_rate, float decay_rate, float max_gain, short hang_time, short attack_wait_time, float gain_filter_alpha, float last_gain);

0 commit comments

Comments
 (0)