diff --git a/csdr.c b/csdr.c index 18472d6..bd74cf2 100644 --- a/csdr.c +++ b/csdr.c @@ -486,6 +486,55 @@ int main(int argc, char *argv[]) return 0; } + if(!strcmp(argv[1],"shift_addfast_cc")) + { + bigbufs=1; + + float starting_phase=0; + float rate; + + int fd; + if(fd=init_fifo(argc,argv)) + { + while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000); + } + else + { + if(argc<=2) return badsyntax("need required parameter (rate)"); + sscanf(argv[2],"%g",&rate); + } + + if(!sendbufsize(initialize_buffers())) return -2; + for(;;) + { + shift_addfast_data_t data=shift_addfast_init(rate); + fprintf(stderr,"shift_addfast_cc: reinitialized to %g\n",rate); + int remain, current_size; + float* ibufptr; + float* obufptr; + for(;;) + { + FEOF_CHECK; + if(!FREAD_C) break; + remain=the_bufsize; + ibufptr=input_buffer; + obufptr=output_buffer; + while(remain) + { + current_size=(remain>1024)?1024:remain; + starting_phase=shift_addfast_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase); + ibufptr+=current_size*2; + obufptr+=current_size*2; + remain-=current_size; + } + FWRITE_C; + if(read_fifo_ctl(fd,"%g\n",&rate)) break; + TRY_YIELD; + } + } + return 0; + } + #ifdef LIBCSDR_GPL if(!strcmp(argv[1],"decimating_shift_addition_cc")) { diff --git a/grc_tests/test_shift_remote.grc b/grc_tests/test_shift_remote.grc new file mode 100644 index 0000000..516635f --- /dev/null +++ b/grc_tests/test_shift_remote.grc @@ -0,0 +1,912 @@ + + + + Thu Jan 15 18:51:48 2015 + + options + + author + + + + window_size + 1280, 1024 + + + category + Custom + + + comment + + + + description + + + + _enabled + True + + + _coordinate + (10, 10) + + + _rotation + 0 + + + generate_options + wx_gui + + + id + top_block + + + max_nouts + 0 + + + realtime_scheduling + + + + run_options + prompt + + + run + True + + + thread_safe_setters + + + + title + + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (8, 195) + + + _rotation + 0 + + + id + rate + + + value + -0.1 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (176, 11) + + + _rotation + 0 + + + id + samp_rate + + + value + 250e3 + + + + analog_sig_source_x + + amp + 1 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + freq + 20000 + + + _coordinate + (8, 75) + + + _rotation + 0 + + + id + analog_sig_source_x_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + offset + 0 + + + type + complex + + + samp_rate + samp_rate + + + waveform + analog.GR_CONST_WAVE + + + + blocks_throttle + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (224, 107) + + + _rotation + 0 + + + id + blocks_throttle_0 + + + ignoretag + True + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samples_per_second + samp_rate + + + type + complex + + + vlen + 1 + + + + ha5kfu_execproc_xx + + alias + + + + commandline + "csdr shift_addition_cc %g"%rate + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (824, 315) + + + _rotation + 0 + + + id + ha5kfu_execproc_xx_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + type + cc + + + + ha5kfu_execproc_xx + + alias + + + + commandline + ncat -vv raspberrypi.local 5321 + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (536, 443) + + + _rotation + 0 + + + id + ha5kfu_execproc_xx_0_0_0_1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + type + cc + + + + notebook + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (272, 11) + + + _rotation + 0 + + + grid_pos + + + + id + nb0 + + + labels + ['original', 'shift_addition_cc','shift_addfast_cc',] + + + notebook + + + + style + wx.NB_TOP + + + + wxgui_fftsink2 + + avg_alpha + 0 + + + average + False + + + baseband_freq + 0 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + fft_size + 1024 + + + freqvar + None + + + _coordinate + (848, 27) + + + _rotation + 0 + + + grid_pos + + + + id + wxgui_fftsink2_0_0 + + + notebook + nb0,0 + + + peak_hold + False + + + ref_level + 0 + + + ref_scale + 2.0 + + + fft_rate + 15 + + + samp_rate + samp_rate + + + title + FFT Plot + + + type + complex + + + win_size + + + + win + None + + + y_divs + 10 + + + y_per_div + 10 + + + + wxgui_fftsink2 + + avg_alpha + 0 + + + average + False + + + baseband_freq + 0 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + fft_size + 1024 + + + freqvar + None + + + _coordinate + (1112, 339) + + + _rotation + 0 + + + grid_pos + + + + id + wxgui_fftsink2_0_1 + + + notebook + nb0,1 + + + peak_hold + False + + + ref_level + 0 + + + ref_scale + 2.0 + + + fft_rate + 15 + + + samp_rate + samp_rate + + + title + FFT Plot + + + type + complex + + + win_size + + + + win + None + + + y_divs + 10 + + + y_per_div + 10 + + + + wxgui_fftsink2 + + avg_alpha + 0 + + + average + False + + + baseband_freq + 0 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + fft_size + 1024 + + + freqvar + None + + + _coordinate + (808, 387) + + + _rotation + 0 + + + grid_pos + + + + id + wxgui_fftsink2_0_1_1 + + + notebook + nb0,2 + + + peak_hold + False + + + ref_level + 0 + + + ref_scale + 2.0 + + + fft_rate + 15 + + + samp_rate + samp_rate + + + title + FFT Plot + + + type + complex + + + win_size + + + + win + None + + + y_divs + 10 + + + y_per_div + 10 + + + + wxgui_scopesink2 + + ac_couple + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1112, 555) + + + _rotation + 0 + + + grid_pos + + + + id + wxgui_scopesink2_0_0 + + + notebook + nb0,1 + + + num_inputs + 1 + + + samp_rate + samp_rate + + + t_scale + 0 + + + title + Scope Plot + + + trig_mode + wxgui.TRIG_MODE_NORM + + + type + complex + + + v_offset + 0 + + + v_scale + 0 + + + win_size + + + + xy_mode + False + + + y_axis_label + Counts + + + + wxgui_scopesink2 + + ac_couple + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (808, 611) + + + _rotation + 0 + + + grid_pos + + + + id + wxgui_scopesink2_0_0_1 + + + notebook + nb0,2 + + + num_inputs + 1 + + + samp_rate + samp_rate + + + t_scale + 0 + + + title + Scope Plot + + + trig_mode + wxgui.TRIG_MODE_NORM + + + type + complex + + + v_offset + 0 + + + v_scale + 0 + + + win_size + + + + xy_mode + False + + + y_axis_label + Counts + + + + analog_sig_source_x_0 + blocks_throttle_0 + 0 + 0 + + + blocks_throttle_0 + ha5kfu_execproc_xx_0_0 + 0 + 0 + + + blocks_throttle_0 + ha5kfu_execproc_xx_0_0_0_1 + 0 + 0 + + + blocks_throttle_0 + wxgui_fftsink2_0_0 + 0 + 0 + + + ha5kfu_execproc_xx_0_0 + wxgui_fftsink2_0_1 + 0 + 0 + + + ha5kfu_execproc_xx_0_0 + wxgui_scopesink2_0_0 + 0 + 0 + + + ha5kfu_execproc_xx_0_0_0_1 + wxgui_fftsink2_0_1_1 + 0 + 0 + + + ha5kfu_execproc_xx_0_0_0_1 + wxgui_scopesink2_0_0_1 + 0 + 0 + + diff --git a/grc_tests/test_shift_remote.sh b/grc_tests/test_shift_remote.sh new file mode 100755 index 0000000..65c7192 --- /dev/null +++ b/grc_tests/test_shift_remote.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# Run this script on a Raspberry Pi 2, while running test_shift_remote.grc on your PC. +# It allows you to debug the NEON-accelerated version of specific DSP algorithms on the target hardware. +TEMPSCRIPT="/tmp/test_shift_remote_exec.sh" +echo '#!/bin/sh\ncsdr shift_addfast_cc -0.1' > $TEMPSCRIPT +cat $TEMPSCRIPT +chmod +x $TEMPSCRIPT +ncat -vvl 5321 -e $TEMPSCRIPT +rm $TEMPSCRIPT diff --git a/libcsdr.c b/libcsdr.c index e6b5b31..09fe664 100644 --- a/libcsdr.c +++ b/libcsdr.c @@ -263,6 +263,45 @@ float shift_table_cc(complexf* input, complexf* output, int input_size, float ra return phase; } + + +shift_addfast_data_t shift_addfast_init(float rate) +{ + shift_addfast_data_t output; + float phase_increment=2*rate*PI; + for(int i=0;i<4;i++) + { + output.dsin[i]=sin(phase_increment*(i+1)); + output.dcos[i]=cos(phase_increment*(i+1)); + } + return output; +} + +float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_addfast_data_t* d, float starting_phase) +{ + //input_size should be multiple of 4 + float phase=starting_phase; + float cos_start=cos(starting_phase); + float sin_start=sin(starting_phase); + float cos_vals[4], sin_vals[4]; + for(int i=0;idcos[i] - sin_start * d->dsin[i]; + sin_vals[i] = sin_start * d->dcos[i] + cos_start * d->dsin[i]; + } + for(int j=0;j<4;j++) + { + iof(output,4*i+j)=cos_vals[j]*iof(input,4*i+j)-sin_vals[j]*qof(input,4*i+j); + qof(output,4*i+j)=sin_vals[j]*iof(input,4*i+j)+cos_vals[j]*qof(input,4*i+j); + } + cos_start = cos_vals[3]; + sin_start = sin_vals[3]; + } + return phase; +} + #ifdef NEON_OPTS #pragma message "We have a faster fir_decimate_cc now." diff --git a/libcsdr.h b/libcsdr.h index ca4a311..f3e154e 100644 --- a/libcsdr.h +++ b/libcsdr.h @@ -156,6 +156,15 @@ void shift_table_deinit(shift_table_data_t table_data); shift_table_data_t shift_table_init(int table_size); float shift_table_cc(complexf* input, complexf* output, int input_size, float rate, shift_table_data_t table_data, float starting_phase); +typedef struct shift_addfast_data_s +{ + float dsin[4]; + float dcos[4]; + +} shift_addfast_data_t; +shift_addfast_data_t shift_addfast_init(float rate); +float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_addfast_data_t* d, float starting_phase); + int log2n(int x); int next_pow2(int x); diff --git a/make_test200 b/make_test200 new file mode 100755 index 0000000..7e5cc05 --- /dev/null +++ b/make_test200 @@ -0,0 +1,2 @@ +#!/bin/bash +gcc test200.c --std=gnu99 -o test200 -DUSE_FFTW -DLIBCSDR_GPL -lcsdr diff --git a/test200.c b/test200.c new file mode 100644 index 0000000..c2166c9 --- /dev/null +++ b/test200.c @@ -0,0 +1,84 @@ +/* +This software is part of libcsdr, a set of simple DSP routines for +Software Defined Radio. + +Copyright (c) 2014-2015, Andras Retzler +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ANDRAS RETZLER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "libcsdr.h" +#include "libcsdr_gpl.h" + +#define T_BUFSIZE (1024*1024/4) +#define T_N (200) + +int main() +{ + fprintf(stderr,"Getting a %d of random samples...\n", T_BUFSIZE); + int urand_fp = open("/dev/urandom",O_RDWR); + unsigned char* buf_u8 = (unsigned char*)malloc(sizeof(unsigned char)*T_BUFSIZE*2); + complexf* buf_c = (complexf*)malloc(sizeof(complexf)*T_BUFSIZE); + complexf* outbuf_c = (complexf*)malloc(sizeof(complexf)*T_BUFSIZE); + read(urand_fp, buf_u8, T_BUFSIZE); + close(urand_fp); + + for(int i=0;i