diff --git a/csdr.c b/csdr.c
index fb5aaf3..457faa7 100644
--- a/csdr.c
+++ b/csdr.c
@@ -1562,6 +1562,20 @@ int main(int argc, char *argv[])
}
}
+ if(!strcmp(argv[1],"fmmod_fc"))
+ {
+ if(!sendbufsize(initialize_buffers())) return -2;
+ float last_phase = 0;
+ for(;;)
+ {
+ FEOF_CHECK;
+ FREAD_R;
+ last_phase = fmmod_fc(input_buffer, (complexf*)output_buffer, the_bufsize, last_phase);
+ FWRITE_C;
+ TRY_YIELD;
+ }
+ }
+
if(!strcmp(argv[1],"none"))
{
return 0;
diff --git a/grc_tests/test_fmmod.grc b/grc_tests/test_fmmod.grc
new file mode 100644
index 0000000..5ed8ee1
--- /dev/null
+++ b/grc_tests/test_fmmod.grc
@@ -0,0 +1,1076 @@
+
+
+
+ Sat Oct 31 16:41:24 2015
+
+ options
+
+ id
+ top_block
+
+
+ _enabled
+ True
+
+
+ title
+
+
+
+ author
+
+
+
+ description
+
+
+
+ window_size
+ 1280, 1024
+
+
+ generate_options
+ wx_gui
+
+
+ category
+ Custom
+
+
+ run_options
+ prompt
+
+
+ run
+ True
+
+
+ max_nouts
+ 0
+
+
+ realtime_scheduling
+
+
+
+ alias
+
+
+
+ _coordinate
+ (10, 10)
+
+
+ _rotation
+ 0
+
+
+
+ variable
+
+ id
+ samp_rate
+
+
+ _enabled
+ True
+
+
+ value
+ 32000
+
+
+ alias
+
+
+
+ _coordinate
+ (176, 11)
+
+
+ _rotation
+ 0
+
+
+
+ notebook
+
+ id
+ nb1
+
+
+ _enabled
+ True
+
+
+ style
+ wx.NB_TOP
+
+
+ labels
+ ['Scope', 'FFT']
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (272, 99)
+
+
+ _rotation
+ 0
+
+
+
+ variable_slider
+
+ id
+ freq
+
+
+ _enabled
+ True
+
+
+ label
+
+
+
+ value
+ 1000
+
+
+ min
+ 0
+
+
+ max
+ samp_rate/2
+
+
+ num_steps
+ 100
+
+
+ style
+ wx.SL_HORIZONTAL
+
+
+ converver
+ float_converter
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (424, 11)
+
+
+ _rotation
+ 0
+
+
+
+ analog_sig_source_x
+
+ id
+ analog_sig_source_x_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ samp_rate
+ samp_rate
+
+
+ waveform
+ analog.GR_COS_WAVE
+
+
+ freq
+ freq
+
+
+ amp
+ amp
+
+
+ offset
+ 0
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (8, 163)
+
+
+ _rotation
+ 0
+
+
+
+ variable_slider
+
+ id
+ amp
+
+
+ _enabled
+ True
+
+
+ label
+
+
+
+ value
+ 0.5
+
+
+ min
+ 0
+
+
+ max
+ 10
+
+
+ num_steps
+ 100
+
+
+ style
+ wx.SL_HORIZONTAL
+
+
+ converver
+ float_converter
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (544, 11)
+
+
+ _rotation
+ 0
+
+
+
+ notebook
+
+ id
+ nb0
+
+
+ _enabled
+ True
+
+
+ style
+ wx.NB_TOP
+
+
+ labels
+ ['Scope', 'FFT']
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (272, 11)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_fftsink2
+
+ id
+ wxgui_fftsink2_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ title
+ FFT Plot of Demodulated Signal
+
+
+ samp_rate
+ samp_rate
+
+
+ baseband_freq
+ 0
+
+
+ y_per_div
+ 10
+
+
+ y_divs
+ 10
+
+
+ ref_level
+ 0
+
+
+ ref_scale
+ 2.0
+
+
+ fft_size
+ 1024
+
+
+ fft_rate
+ 15
+
+
+ peak_hold
+ False
+
+
+ average
+ False
+
+
+ avg_alpha
+ 0
+
+
+ win
+ None
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,1
+
+
+ freqvar
+ None
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (1016, 827)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ title
+ Scope Plot of Demodulated Signal
+
+
+ samp_rate
+ samp_rate
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,0
+
+
+ trig_mode
+ wxgui.TRIG_MODE_AUTO
+
+
+ y_axis_label
+ Counts
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (1024, 643)
+
+
+ _rotation
+ 0
+
+
+
+ blocks_throttle
+
+ id
+ blocks_throttle_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ samples_per_second
+ samp_rate
+
+
+ vlen
+ 1
+
+
+ ignoretag
+ True
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (176, 195)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ cf
+
+
+ commandline
+ csdr fmdemod_quadri_cf
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (768, 675)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_fftsink2
+
+ id
+ wxgui_fftsink2_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ complex
+
+
+ title
+ FFT Plot of Processed Signal (csdr)
+
+
+ samp_rate
+ samp_rate
+
+
+ baseband_freq
+ 0
+
+
+ y_per_div
+ 10
+
+
+ y_divs
+ 10
+
+
+ ref_level
+ 0
+
+
+ ref_scale
+ 2.0
+
+
+ fft_size
+ 1024
+
+
+ fft_rate
+ 15
+
+
+ peak_hold
+ False
+
+
+ average
+ False
+
+
+ avg_alpha
+ 0
+
+
+ win
+ None
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb1,1
+
+
+ freqvar
+ None
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (1000, 395)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ complex
+
+
+ title
+ Scope Plot of Processed Signal (csdr)
+
+
+ samp_rate
+ samp_rate
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb1,0
+
+
+ trig_mode
+ wxgui.TRIG_MODE_AUTO
+
+
+ y_axis_label
+ Counts
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (992, 171)
+
+
+ _rotation
+ 0
+
+
+
+ analog_wfm_tx
+
+ id
+ analog_wfm_tx_0
+
+
+ _enabled
+ False
+
+
+ audio_rate
+ samp_rate
+
+
+ quad_rate
+ samp_rate
+
+
+ tau
+ 75e-6
+
+
+ max_dev
+ 75e3
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (472, 499)
+
+
+ _rotation
+ 0
+
+
+
+ blocks_float_to_complex
+
+ id
+ blocks_float_to_complex_0
+
+
+ _enabled
+ True
+
+
+ vlen
+ 1
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (552, 376)
+
+
+ _rotation
+ 0
+
+
+
+ blocks_deinterleave
+
+ id
+ blocks_deinterleave_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ num_streams
+ 2
+
+
+ blocksize
+ 1
+
+
+ vlen
+ 1
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (384, 376)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0
+
+
+ _enabled
+ True
+
+
+ type
+ ff
+
+
+ commandline
+ csdr fmmod_fc
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (448, 195)
+
+
+ _rotation
+ 0
+
+
+
+ analog_sig_source_x_0
+ blocks_throttle_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ ha5kfu_execproc_xx_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0
+ blocks_deinterleave_0
+ 0
+ 0
+
+
+ blocks_deinterleave_0
+ blocks_float_to_complex_0
+ 0
+ 0
+
+
+ blocks_deinterleave_0
+ blocks_float_to_complex_0
+ 1
+ 1
+
+
+ blocks_float_to_complex_0
+ wxgui_scopesink2_0_0
+ 0
+ 0
+
+
+ blocks_float_to_complex_0
+ wxgui_fftsink2_0_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0_0
+ wxgui_scopesink2_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0_0
+ wxgui_fftsink2_0
+ 0
+ 0
+
+
+ blocks_float_to_complex_0
+ ha5kfu_execproc_xx_0_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ analog_wfm_tx_0
+ 0
+ 0
+
+
+ analog_wfm_tx_0
+ ha5kfu_execproc_xx_0_0
+ 0
+ 0
+
+
+ analog_wfm_tx_0
+ wxgui_fftsink2_0_0
+ 0
+ 0
+
+
+ analog_wfm_tx_0
+ wxgui_scopesink2_0_0
+ 0
+ 0
+
+
diff --git a/libcsdr.c b/libcsdr.c
index 2317856..598d1d2 100644
--- a/libcsdr.c
+++ b/libcsdr.c
@@ -834,6 +834,20 @@ void add_dcoffset_cc(complexf* input, complexf* output, int input_size)
for(int i=0;iPI) phase-=2*PI;
+ while(phase<=-PI) phase+=2*PI;
+ iof(output,i)=cos(phase);
+ qof(output,i)=sin(phase);
+ }
+ return phase;
+}
+
/*
______ _ ______ _ _______ __
| ____| | | | ____| (_) |__ __| / _|
diff --git a/libcsdr.h b/libcsdr.h
index e99d010..a2e80c4 100644
--- a/libcsdr.h
+++ b/libcsdr.h
@@ -163,6 +163,7 @@ void apply_fir_fft_cc(FFT_PLAN_T* plan, FFT_PLAN_T* plan_inverse, complexf* taps
void gain_ff(float* input, float* output, int input_size, float gain);
void add_dcoffset_cc(complexf* input, complexf* output, int input_size);
+float fmmod_fc(float* input, complexf* output, int input_size, float last_phase);
void convert_u8_f(unsigned char* input, float* output, int input_size);
void convert_f_u8(float* input, unsigned char* output, int input_size);