diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38f2fd2..558852f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,7 @@
# Project setup
########################################################################
cmake_minimum_required(VERSION 2.6)
+set(CMAKE_CXX_STANDARD 11)
project(gr-digitalhf CXX C)
enable_testing()
@@ -148,7 +149,7 @@ find_package(Doxygen)
# components required to the list of GR_REQUIRED_COMPONENTS (in all
# caps such as FILTER or FFT) and change the version to the minimum
# API compatible version required.
-set(GR_REQUIRED_COMPONENTS RUNTIME DIGITAL)
+set(GR_REQUIRED_COMPONENTS RUNTIME DIGITAL VOLK)
find_package(Gnuradio "3.7.2" REQUIRED)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules)
include(GrVersion)
diff --git a/examples/1st.grc b/examples/1st.grc
index 50a7750..31b039f 100644
--- a/examples/1st.grc
+++ b/examples/1st.grc
@@ -117,7 +117,7 @@
value
- 10*sps
+ 12*sps
@@ -144,7 +144,7 @@
value
- 5*sps
+ 12*sps
@@ -395,6 +395,14 @@
id
digitalhf_adaptive_dfe_0
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
sps
sps
@@ -416,6 +424,373 @@
STANAG_4285
+
+ qtgui_time_sink_x
+
+ autoscale
+ False
+
+
+ axislabels
+ True
+
+
+ alias
+
+
+
+ comment
+
+
+
+ ctrlpanel
+ False
+
+
+ affinity
+
+
+
+ entags
+ True
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (874, 176)
+
+
+ gui_hint
+
+
+
+ _rotation
+ 0
+
+
+ grid
+ False
+
+
+ id
+ qtgui_time_sink_x_0
+
+
+ legend
+ True
+
+
+ alpha1
+ 1.0
+
+
+ color1
+ "blue"
+
+
+ label1
+
+
+
+ marker1
+ -1
+
+
+ style1
+ 1
+
+
+ width1
+ 1
+
+
+ alpha10
+ 1.0
+
+
+ color10
+ "blue"
+
+
+ label10
+
+
+
+ marker10
+ -1
+
+
+ style10
+ 1
+
+
+ width10
+ 1
+
+
+ alpha2
+ 1.0
+
+
+ color2
+ "red"
+
+
+ label2
+
+
+
+ marker2
+ -1
+
+
+ style2
+ 1
+
+
+ width2
+ 1
+
+
+ alpha3
+ 1.0
+
+
+ color3
+ "green"
+
+
+ label3
+
+
+
+ marker3
+ -1
+
+
+ style3
+ 1
+
+
+ width3
+ 1
+
+
+ alpha4
+ 1.0
+
+
+ color4
+ "black"
+
+
+ label4
+
+
+
+ marker4
+ -1
+
+
+ style4
+ 1
+
+
+ width4
+ 1
+
+
+ alpha5
+ 1.0
+
+
+ color5
+ "cyan"
+
+
+ label5
+
+
+
+ marker5
+ -1
+
+
+ style5
+ 1
+
+
+ width5
+ 1
+
+
+ alpha6
+ 1.0
+
+
+ color6
+ "magenta"
+
+
+ label6
+
+
+
+ marker6
+ -1
+
+
+ style6
+ 1
+
+
+ width6
+ 1
+
+
+ alpha7
+ 1.0
+
+
+ color7
+ "yellow"
+
+
+ label7
+
+
+
+ marker7
+ -1
+
+
+ style7
+ 1
+
+
+ width7
+ 1
+
+
+ alpha8
+ 1.0
+
+
+ color8
+ "dark red"
+
+
+ label8
+
+
+
+ marker8
+ -1
+
+
+ style8
+ 1
+
+
+ width8
+ 1
+
+
+ alpha9
+ 1.0
+
+
+ color9
+ "dark green"
+
+
+ label9
+
+
+
+ marker9
+ -1
+
+
+ style9
+ 1
+
+
+ width9
+ 1
+
+
+ name
+ ""
+
+
+ nconnections
+ 1
+
+
+ size
+ 1024
+
+
+ srate
+ samp_rate
+
+
+ stemplot
+ False
+
+
+ tr_chan
+ 0
+
+
+ tr_delay
+ 0
+
+
+ tr_level
+ 0.0
+
+
+ tr_mode
+ qtgui.TRIG_MODE_FREE
+
+
+ tr_slope
+ qtgui.TRIG_SLOPE_POS
+
+
+ tr_tag
+ ""
+
+
+ type
+ complex
+
+
+ update_time
+ 0.10
+
+
+ ylabel
+ Amplitude
+
+
+ yunit
+ ""
+
+
+ ymax
+ 1
+
+
+ ymin
+ -1
+
+
analog_noise_source_x_0
blocks_throttle_0
@@ -428,4 +803,10 @@
0
0
+
+ digitalhf_adaptive_dfe_0
+ qtgui_time_sink_x_0
+ 0
+ 0
+
diff --git a/examples/test_cc.grc b/examples/test_cc.grc
new file mode 100644
index 0000000..86267c2
--- /dev/null
+++ b/examples/test_cc.grc
@@ -0,0 +1,2202 @@
+
+
+
+ Fri Oct 19 14:08:05 2018
+
+ options
+
+ author
+
+
+
+ window_size
+
+
+
+ category
+ [GRC Hier Blocks]
+
+
+ comment
+
+
+
+ copyright
+
+
+
+ description
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (8, 8)
+
+
+ _rotation
+ 0
+
+
+ generate_options
+ qt_gui
+
+
+ hier_block_src_path
+ .:
+
+
+ id
+ top_block
+
+
+ max_nouts
+ 0
+
+
+ qt_qss_theme
+
+
+
+ realtime_scheduling
+
+
+
+ run_command
+ {python} -u {filename}
+
+
+ run_options
+ prompt
+
+
+ run
+ True
+
+
+ sizing_mode
+ fixed
+
+
+ thread_safe_setters
+
+
+
+ title
+
+
+
+ placement
+ (0,0)
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (266, 570)
+
+
+ _rotation
+ 0
+
+
+ id
+ dummy
+
+
+ value
+ [lpz[0].extend(x) for x in lpz[1:]]
+
+
+
+ variable_qtgui_range
+
+ comment
+
+
+
+ value
+ 4932
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1130, 5)
+
+
+ gui_hint
+
+
+
+ _rotation
+ 0
+
+
+ id
+ freq
+
+
+ label
+ frequency
+
+
+ min_len
+ 200
+
+
+ orient
+ Qt.Horizontal
+
+
+ start
+ 0
+
+
+ step
+ 0.0001
+
+
+ stop
+ 30e3
+
+
+ rangeType
+ float
+
+
+ widget
+ counter_slider
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (320, 5)
+
+
+ _rotation
+ 0
+
+
+ id
+ lpz
+
+
+ value
+ [[x,x,x,x,x] for x in STANAG_4285.PhysicalLayer.get_preamble()['symb'].tolist()]
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (554, 5)
+
+
+ _rotation
+ 0
+
+
+ id
+ nB
+
+
+ value
+ 10*sps
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (629, 5)
+
+
+ _rotation
+ 0
+
+
+ id
+ nF
+
+
+ value
+ 10*sps
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (704, 5)
+
+
+ _rotation
+ 0
+
+
+ id
+ nW
+
+
+ value
+ 4
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (224, 5)
+
+
+ _rotation
+ 0
+
+
+ id
+ samp_rate
+
+
+ value
+ 12000
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (480, 5)
+
+
+ _rotation
+ 0
+
+
+ id
+ sps
+
+
+ value
+ 5
+
+
+
+ blocks_complex_to_mag
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (906, 421)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_complex_to_mag_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ vlen
+ 1
+
+
+
+ blocks_float_to_complex
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (234, 133)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_float_to_complex_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ vlen
+ 1
+
+
+
+ blocks_multiply_const_vxx
+
+ alias
+
+
+
+ comment
+
+
+
+ const
+ 4
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (416, 154)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_multiply_const_vxx_0
+
+
+ type
+ complex
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ vlen
+ 1
+
+
+
+ blocks_tag_debug
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ display
+ True
+
+
+ _enabled
+ 0
+
+
+ _coordinate
+ (1034, 282)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_tag_debug_0
+
+
+ type
+ complex
+
+
+ filter
+ ""
+
+
+ name
+
+
+
+ num_inputs
+ 1
+
+
+ vlen
+ 1
+
+
+
+ blocks_throttle
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (576, 154)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_throttle_0
+
+
+ ignoretag
+ True
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ samples_per_second
+ samp_rate
+
+
+ type
+ complex
+
+
+ vlen
+ 1
+
+
+
+ blocks_wavfile_source
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ file
+ /Users/chm/Downloads/sielsdr.ddns.net_2018-10-26T11_30_27Z_6768.50_iq.wav
+
+
+ _coordinate
+ (10, 133)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_wavfile_source_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ nchan
+ 2
+
+
+ repeat
+ False
+
+
+
+ digitalhf_adaptive_dfe
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (85, 410)
+
+
+ _rotation
+ 0
+
+
+ id
+ digitalhf_adaptive_dfe_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ sps
+ sps
+
+
+ nB
+ nB
+
+
+ nF
+ nF
+
+
+ nW
+ nW
+
+
+ py_obj_name
+ STANAG_4285
+
+
+
+ import
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (917, 10)
+
+
+ _rotation
+ 0
+
+
+ id
+ import_0
+
+
+ import
+ import digitalhf.physical_layer.STANAG_4285 as STANAG_4285
+
+
+
+ import
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (906, 64)
+
+
+ _rotation
+ 0
+
+
+ id
+ import_0_0
+
+
+ import
+ from gnuradio import gr
+
+
+
+ digital_corr_est_cc
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (746, 133)
+
+
+ _rotation
+ 0
+
+
+ id
+ preamble
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ sps
+ sps
+
+
+ symbols
+ lpz[0]
+
+
+ mark_delay
+ nF+2
+
+
+ threshold_method
+ digital.corr_est_cc.THRESHOLD_DYNAMIC
+
+
+ threshold
+ 0.5
+
+
+
+ qtgui_const_sink_x
+
+ autoscale
+ False
+
+
+ axislabels
+ True
+
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (469, 432)
+
+
+ gui_hint
+
+
+
+ _rotation
+ 0
+
+
+ grid
+ True
+
+
+ id
+ qtgui_const_sink_x_0
+
+
+ legend
+ True
+
+
+ alpha1
+ 1
+
+
+ color1
+ "blue"
+
+
+ label1
+
+
+
+ marker1
+ 0
+
+
+ style1
+ 0
+
+
+ width1
+ 1
+
+
+ alpha10
+ 1.0
+
+
+ color10
+ "red"
+
+
+ label10
+
+
+
+ marker10
+ 0
+
+
+ style10
+ 0
+
+
+ width10
+ 1
+
+
+ alpha2
+ 1.0
+
+
+ color2
+ "red"
+
+
+ label2
+
+
+
+ marker2
+ 0
+
+
+ style2
+ 0
+
+
+ width2
+ 1
+
+
+ alpha3
+ 1.0
+
+
+ color3
+ "red"
+
+
+ label3
+
+
+
+ marker3
+ 0
+
+
+ style3
+ 0
+
+
+ width3
+ 1
+
+
+ alpha4
+ 1.0
+
+
+ color4
+ "red"
+
+
+ label4
+
+
+
+ marker4
+ 0
+
+
+ style4
+ 0
+
+
+ width4
+ 1
+
+
+ alpha5
+ 1.0
+
+
+ color5
+ "red"
+
+
+ label5
+
+
+
+ marker5
+ 0
+
+
+ style5
+ 0
+
+
+ width5
+ 1
+
+
+ alpha6
+ 1.0
+
+
+ color6
+ "red"
+
+
+ label6
+
+
+
+ marker6
+ 0
+
+
+ style6
+ 0
+
+
+ width6
+ 1
+
+
+ alpha7
+ 1.0
+
+
+ color7
+ "red"
+
+
+ label7
+
+
+
+ marker7
+ 0
+
+
+ style7
+ 0
+
+
+ width7
+ 1
+
+
+ alpha8
+ 1.0
+
+
+ color8
+ "red"
+
+
+ label8
+
+
+
+ marker8
+ 0
+
+
+ style8
+ 0
+
+
+ width8
+ 1
+
+
+ alpha9
+ 1.0
+
+
+ color9
+ "red"
+
+
+ label9
+
+
+
+ marker9
+ 0
+
+
+ style9
+ 0
+
+
+ width9
+ 1
+
+
+ name
+ ""
+
+
+ nconnections
+ 1
+
+
+ size
+ 1024
+
+
+ tr_chan
+ 0
+
+
+ tr_level
+ 0.0
+
+
+ tr_mode
+ qtgui.TRIG_MODE_FREE
+
+
+ tr_slope
+ qtgui.TRIG_SLOPE_POS
+
+
+ tr_tag
+ ""
+
+
+ type
+ complex
+
+
+ update_time
+ 0.1
+
+
+ xmax
+ 2
+
+
+ xmin
+ -2
+
+
+ ymax
+ 2
+
+
+ ymin
+ -2
+
+
+
+ qtgui_time_sink_x
+
+ autoscale
+ True
+
+
+ axislabels
+ True
+
+
+ alias
+
+
+
+ comment
+
+
+
+ ctrlpanel
+ False
+
+
+ affinity
+
+
+
+ entags
+ True
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1098, 410)
+
+
+ gui_hint
+
+
+
+ _rotation
+ 0
+
+
+ grid
+ False
+
+
+ id
+ qtgui_time_sink_x_0
+
+
+ legend
+ True
+
+
+ alpha1
+ 1.0
+
+
+ color1
+ "blue"
+
+
+ label1
+ err
+
+
+ marker1
+ -1
+
+
+ style1
+ 1
+
+
+ width1
+ 1
+
+
+ alpha10
+ 1.0
+
+
+ color10
+ "blue"
+
+
+ label10
+
+
+
+ marker10
+ -1
+
+
+ style10
+ 1
+
+
+ width10
+ 1
+
+
+ alpha2
+ 1.0
+
+
+ color2
+ "red"
+
+
+ label2
+ rate
+
+
+ marker2
+ -1
+
+
+ style2
+ 1
+
+
+ width2
+ 1
+
+
+ alpha3
+ 1.0
+
+
+ color3
+ "green"
+
+
+ label3
+ phase
+
+
+ marker3
+ -1
+
+
+ style3
+ 1
+
+
+ width3
+ 1
+
+
+ alpha4
+ 1.0
+
+
+ color4
+ "black"
+
+
+ label4
+
+
+
+ marker4
+ -1
+
+
+ style4
+ 1
+
+
+ width4
+ 1
+
+
+ alpha5
+ 1.0
+
+
+ color5
+ "cyan"
+
+
+ label5
+
+
+
+ marker5
+ -1
+
+
+ style5
+ 1
+
+
+ width5
+ 1
+
+
+ alpha6
+ 1.0
+
+
+ color6
+ "magenta"
+
+
+ label6
+
+
+
+ marker6
+ -1
+
+
+ style6
+ 1
+
+
+ width6
+ 1
+
+
+ alpha7
+ 1.0
+
+
+ color7
+ "yellow"
+
+
+ label7
+
+
+
+ marker7
+ -1
+
+
+ style7
+ 1
+
+
+ width7
+ 1
+
+
+ alpha8
+ 1.0
+
+
+ color8
+ "dark red"
+
+
+ label8
+
+
+
+ marker8
+ -1
+
+
+ style8
+ 1
+
+
+ width8
+ 1
+
+
+ alpha9
+ 1.0
+
+
+ color9
+ "dark green"
+
+
+ label9
+
+
+
+ marker9
+ -1
+
+
+ style9
+ 1
+
+
+ width9
+ 1
+
+
+ name
+ ""
+
+
+ nconnections
+ 1
+
+
+ size
+ 1024
+
+
+ srate
+ samp_rate
+
+
+ stemplot
+ False
+
+
+ tr_chan
+ 0
+
+
+ tr_delay
+ 0.02
+
+
+ tr_level
+ 0.0
+
+
+ tr_mode
+ qtgui.TRIG_MODE_TAG
+
+
+ tr_slope
+ qtgui.TRIG_SLOPE_POS
+
+
+ tr_tag
+ "time_est"
+
+
+ type
+ float
+
+
+ update_time
+ .1
+
+
+ ylabel
+ preamble correlation
+
+
+ yunit
+ ""
+
+
+ ymax
+ 800
+
+
+ ymin
+ 0
+
+
+
+ qtgui_time_sink_x
+
+ autoscale
+ True
+
+
+ axislabels
+ True
+
+
+ alias
+
+
+
+ comment
+
+
+
+ ctrlpanel
+ False
+
+
+ affinity
+
+
+
+ entags
+ True
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1077, 197)
+
+
+ gui_hint
+
+
+
+ _rotation
+ 0
+
+
+ grid
+ False
+
+
+ id
+ qtgui_time_sink_x_0_0
+
+
+ legend
+ True
+
+
+ alpha1
+ 1.0
+
+
+ color1
+ "blue"
+
+
+ label1
+ I
+
+
+ marker1
+ -1
+
+
+ style1
+ 1
+
+
+ width1
+ 1
+
+
+ alpha10
+ 1.0
+
+
+ color10
+ "blue"
+
+
+ label10
+
+
+
+ marker10
+ -1
+
+
+ style10
+ 1
+
+
+ width10
+ 1
+
+
+ alpha2
+ 1.0
+
+
+ color2
+ "red"
+
+
+ label2
+ Q
+
+
+ marker2
+ -1
+
+
+ style2
+ 1
+
+
+ width2
+ 1
+
+
+ alpha3
+ 1.0
+
+
+ color3
+ "green"
+
+
+ label3
+ phase
+
+
+ marker3
+ -1
+
+
+ style3
+ 1
+
+
+ width3
+ 1
+
+
+ alpha4
+ 1.0
+
+
+ color4
+ "black"
+
+
+ label4
+
+
+
+ marker4
+ -1
+
+
+ style4
+ 1
+
+
+ width4
+ 1
+
+
+ alpha5
+ 1.0
+
+
+ color5
+ "cyan"
+
+
+ label5
+
+
+
+ marker5
+ -1
+
+
+ style5
+ 1
+
+
+ width5
+ 1
+
+
+ alpha6
+ 1.0
+
+
+ color6
+ "magenta"
+
+
+ label6
+
+
+
+ marker6
+ -1
+
+
+ style6
+ 1
+
+
+ width6
+ 1
+
+
+ alpha7
+ 1.0
+
+
+ color7
+ "yellow"
+
+
+ label7
+
+
+
+ marker7
+ -1
+
+
+ style7
+ 1
+
+
+ width7
+ 1
+
+
+ alpha8
+ 1.0
+
+
+ color8
+ "dark red"
+
+
+ label8
+
+
+
+ marker8
+ -1
+
+
+ style8
+ 1
+
+
+ width8
+ 1
+
+
+ alpha9
+ 1.0
+
+
+ color9
+ "dark green"
+
+
+ label9
+
+
+
+ marker9
+ -1
+
+
+ style9
+ 1
+
+
+ width9
+ 1
+
+
+ name
+ ""
+
+
+ nconnections
+ 1
+
+
+ size
+ 1024
+
+
+ srate
+ samp_rate
+
+
+ stemplot
+ False
+
+
+ tr_chan
+ 0
+
+
+ tr_delay
+ 0.02
+
+
+ tr_level
+ 0.0
+
+
+ tr_mode
+ qtgui.TRIG_MODE_TAG
+
+
+ tr_slope
+ qtgui.TRIG_SLOPE_POS
+
+
+ tr_tag
+ "time_est"
+
+
+ type
+ complex
+
+
+ update_time
+ .1
+
+
+ ylabel
+ preamble correlation
+
+
+ yunit
+ ""
+
+
+ ymax
+ 2
+
+
+ ymin
+ -2
+
+
+
+ qtgui_waterfall_sink_x
+
+ axislabels
+ True
+
+
+ bw
+ samp_rate
+
+
+ alias
+
+
+
+ fc
+ 0
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ fftsize
+ 128
+
+
+ _coordinate
+ (1077, 112)
+
+
+ gui_hint
+
+
+
+ _rotation
+ 0
+
+
+ grid
+ False
+
+
+ id
+ qtgui_waterfall_sink_x_0
+
+
+ int_max
+ 10
+
+
+ int_min
+ -140
+
+
+ legend
+ True
+
+
+ alpha1
+ 1.0
+
+
+ color1
+ 0
+
+
+ label1
+
+
+
+ alpha10
+ 1.0
+
+
+ color10
+ 0
+
+
+ label10
+
+
+
+ alpha2
+ 1.0
+
+
+ color2
+ 0
+
+
+ label2
+
+
+
+ alpha3
+ 1.0
+
+
+ color3
+ 0
+
+
+ label3
+
+
+
+ alpha4
+ 1.0
+
+
+ color4
+ 0
+
+
+ label4
+
+
+
+ alpha5
+ 1.0
+
+
+ color5
+ 0
+
+
+ label5
+
+
+
+ alpha6
+ 1.0
+
+
+ color6
+ 0
+
+
+ label6
+
+
+
+ alpha7
+ 1.0
+
+
+ color7
+ 0
+
+
+ label7
+
+
+
+ alpha8
+ 1.0
+
+
+ color8
+ 0
+
+
+ label8
+
+
+
+ alpha9
+ 1.0
+
+
+ color9
+ 0
+
+
+ label9
+
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ name
+ ""
+
+
+ nconnections
+ 1
+
+
+ showports
+ True
+
+
+ freqhalf
+ True
+
+
+ type
+ complex
+
+
+ update_time
+ 0.10
+
+
+ wintype
+ firdes.WIN_BLACKMAN_hARRIS
+
+
+
+ blocks_complex_to_mag_0
+ qtgui_time_sink_x_0
+ 0
+ 0
+
+
+ blocks_float_to_complex_0
+ blocks_multiply_const_vxx_0
+ 0
+ 0
+
+
+ blocks_multiply_const_vxx_0
+ blocks_throttle_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ preamble
+ 0
+ 0
+
+
+ blocks_wavfile_source_0
+ blocks_float_to_complex_0
+ 0
+ 0
+
+
+ blocks_wavfile_source_0
+ blocks_float_to_complex_0
+ 1
+ 1
+
+
+ digitalhf_adaptive_dfe_0
+ qtgui_const_sink_x_0
+ 0
+ 0
+
+
+ preamble
+ blocks_complex_to_mag_0
+ 1
+ 0
+
+
+ preamble
+ blocks_tag_debug_0
+ 0
+ 0
+
+
+ preamble
+ digitalhf_adaptive_dfe_0
+ 0
+ 0
+
+
+ preamble
+ qtgui_time_sink_x_0_0
+ 0
+ 0
+
+
+ preamble
+ qtgui_waterfall_sink_x_0
+ 0
+ 0
+
+
diff --git a/grc/digitalhf_adaptive_dfe.xml b/grc/digitalhf_adaptive_dfe.xml
index 4d7a928..58b2cbd 100644
--- a/grc/digitalhf_adaptive_dfe.xml
+++ b/grc/digitalhf_adaptive_dfe.xml
@@ -51,8 +51,9 @@
* type
* vlen
* optional (set to 1 for optional inputs) -->
-
-
-
-
+
diff --git a/lib/adaptive_dfe_impl.cc b/lib/adaptive_dfe_impl.cc
index aaa714c..c0ec835 100644
--- a/lib/adaptive_dfe_impl.cc
+++ b/lib/adaptive_dfe_impl.cc
@@ -23,6 +23,7 @@
#endif
#include
+#include
#include "adaptive_dfe_impl.h"
namespace gr {
@@ -31,7 +32,7 @@ namespace digitalhf {
namespace {
class GILLock {
PyGILState_STATE _state;
- public:
+public:
GILLock()
:_state(PyGILState_Ensure()) {}
~GILLock() {
@@ -39,6 +40,7 @@ class GILLock {
}
} ;
}
+
adaptive_dfe::sptr
adaptive_dfe::make(int sps, // samples per symbol
int nB, // number of forward FIR taps
@@ -60,29 +62,35 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol
std::string python_module_name)
: gr::block("adaptive_dfe",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
- gr::io_signature::make(0, 0, sizeof(gr_complex)))
+ gr::io_signature::make(1, 1, sizeof(gr_complex)))
, _sps(sps)
, _nB(nB)
, _nF(nF)
, _nW(nW)
+ , _mu(0.01)
+ , _alpha(0.0005)
, _py_module_name(python_module_name)
, _physicalLayer()
- , _taps_samples(nB+nF+1)
- , _taps_symbols(nW)
+ , _taps_samples(nullptr)
+ , _taps_symbols(nullptr)
+ , _hist_samples(nullptr)
+ , _hist_symbols(nullptr)
+ , _hist_sample_index(0)
+ , _hist_symbol_index(0)
+ , _sample_counter(0)
, _constellations()
, _constellation_index()
, _symbols()
, _scramble()
+ , _descrambled_symbols()
+ , _symbol_counter(0)
+ , _sum_phase_diff(0)
+ , _df(0)
+ , _phase(0)
+ , _b{0.338187046465954, -0.288839024460507}
+ , _ud(0)
+ , _state(WAIT_FOR_PREAMBLE)
{
- // make sure python is ready for threading
- if( Py_IsInitialized() ){
- if(PyEval_ThreadsInitialized() != 1 ){
- PyEval_InitThreads();
- }
- boost::python::numpy::initialize();
- } else {
- throw std::runtime_error("dont use es_pyhandler without python!");
- }
}
/*
@@ -95,7 +103,7 @@ adaptive_dfe_impl::~adaptive_dfe_impl()
void
adaptive_dfe_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
- /* <+forecast+> e.g. ninput_items_required[0] = noutput_items */
+ ninput_items_required[0] = _sps*noutput_items;
}
int
@@ -104,21 +112,177 @@ adaptive_dfe_impl::general_work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
+ gr::thread::scoped_lock lock(d_setlock);
gr_complex const* in = (gr_complex const *)input_items[0];
+ gr_complex *out = (gr_complex *)output_items[0];
- GILLock lock;
- // TODO: wait for preamble correlation tag etc...
- update_frame_information(_physicalLayer.attr("get_frame")());
- update_doppler_information(_physicalLayer.attr("get_doppler")()); // symbols
+ int nout = 0;
+ int i = 0;
+ for (; i M_PI)
+ _phase -= 2*M_PI;
+ if (_phase < -M_PI)
+ _phase += 2*M_PI;
- consume_each (noutput_items);
+ _hist_samples[_hist_sample_index] = _hist_samples[_hist_sample_index+_nB+_nF+1] = in[i] * std::exp(gr_complex(0,_phase));
+ if (++_hist_sample_index == _nB+_nF+1)
+ _hist_sample_index = 0;
+
+ if (_state == WAIT_FOR_PREAMBLE) {
+ std::vector v;
+ get_tags_in_window(v, 0, i,i+1);
+ float phase_est = 0;
+ float corr_est = 0;
+ uint64_t offset = 0;
+ for (int j=0; j 130e3) {
+ offset = v[j].offset - nitems_read(0);
+ break;
+ }
+ }
+ }
+ if (corr_est > 130e3) {
+ _state = DO_FILTER;
+ _sample_counter = 0;
+ _symbol_counter = 0;
+ // _symbols.clear();
+ // _scramble.clear();
+ _descrambled_symbols.clear();
+ // _hist_sample_index = 0;
+ _hist_symbol_index = 0;
+ std::fill_n(_hist_symbols, 2*_nW, gr_complex(0));
+ std::fill_n(_taps_samples, _nB+_nF+1, gr_complex(0));
+ std::fill_n(_taps_symbols, _nW, gr_complex(0));
+ //_phase = -phase_est;
+ _taps_samples[_nB+1] = std::exp(gr_complex(0, -phase_est));
+ _taps_symbols[0] = 1;
+ GILLock lock;
+ try {
+ update_frame_information(_physicalLayer.attr("get_frame")());
+ } catch (boost::python::error_already_set const&) {
+ PyErr_Print();
+ }
+ }
+ }
+ if (_state == DO_FILTER) {
+ gr_complex dot_samples = 0;
+ // volk_32fc_x2_dot_prod_32fc(&dot_samples,
+ // &_hist_samples.front()+_hist_sample_index,
+ // &_taps_samples.front(),
+ // _taps_samples.size());
+ gr_complex filter_output = dot_samples;
+ // if (_sample_counter < 80*5)
+ // std::cout << "SAMPLE " << _sample_counter << " " << dot_samples << std::endl;
+ if ((_sample_counter%_sps) == 0) {
+ if (_symbol_counter == _symbols.size()) {
+ _symbol_counter = 0;
+ GILLock lock;
+ try {
+ boost::python::numpy::ndarray s = boost::python::numpy::from_data(&_descrambled_symbols.front(),
+ boost::python::numpy::dtype::get_builtin(),
+ boost::python::make_tuple(_descrambled_symbols.size()),
+ boost::python::make_tuple(sizeof(gr_complex)),
+ boost::python::object());
+ update_doppler_information(_physicalLayer.attr("get_doppler")(s));
+ update_frame_information(_physicalLayer.attr("get_frame")());
+ } catch (boost::python::error_already_set const&) {
+ PyErr_Print();
+ }
+ }
+ gr_complex known_symbol = _symbols[_symbol_counter];
+ bool is_known = true;
+ for (int k=0; k<1; ++k) {
+ filter_output = 0;
+#if 1
+ volk_32fc_x2_dot_prod_32fc(&filter_output,
+ _hist_samples+_hist_sample_index,
+ _taps_samples,
+ _nB+_nF+1);
+#else
+ for (int l=0; l<_nB+_nF+1; ++l) {
+ assert(_hist_sample_index+l < 2*(_nB+_nF+1));
+ filter_output += _hist_samples[_hist_sample_index+l]*_taps_samples[l];
+ }
+#endif
+ gr_complex dot_symbols=0;
+ for (int l=0; l<_nW; ++l) {
+ assert(_hist_symbol_index+l < 2*_nW);
+ dot_symbols += _hist_symbols[_hist_symbol_index+l]*_taps_symbols[l];
+ }
+ filter_output += dot_symbols;
+ if (std::abs(known_symbol) < 1e-5) { // not known
+ is_known = false;
+ gr_complex descrambled_filter_output = std::conj(_scramble[_symbol_counter]) * filter_output;
+ gr::digital::constellation_sptr constell = _constellations[_constellation_index];
+ unsigned int jc = constell->decision_maker(&descrambled_filter_output);
+ constell->map_to_points(jc, &descrambled_filter_output);
+ known_symbol = _scramble[_symbol_counter] * descrambled_filter_output;
+ }
+ gr_complex err = filter_output - known_symbol;
+ if (_symbol_counter >= 0) {
+ for (int j=0; j<_nB+_nF+1; ++j) {
+ _taps_samples[j] -= _mu*err*std::conj(_hist_samples[_hist_sample_index+j]);
+ }
+ for (int j=0; j<_nW; ++j) {
+ assert(_hist_symbol_index+j < 2*_nW);
+ _taps_symbols[j] -= _mu*err*std::conj(_hist_symbols[_hist_symbol_index+j]) + _alpha*_taps_symbols[j];
+ }
+ }
+ // std::cout << "filter: " << _symbol_counter << " " << _sample_counter << " " << filter_output << " " << known_symbol << " " << std::abs(err) << std::endl;
+ }
+ if (is_known) {
+ _taps_symbols[_hist_symbol_index] = _taps_symbols[_hist_symbol_index + _nW] = known_symbol;
+ if (++_hist_symbol_index == _nW)
+ _hist_symbol_index = 0;
+ }
+ _descrambled_symbols[_symbol_counter] = filter_output*std::conj(_scramble[_symbol_counter]);
+ out[nout++] = filter_output;
+ ++_symbol_counter;
+ }
+ _sample_counter += 1;
+ }
+ }
+
+ consume(0, i);
// Tell runtime system how many output items we produced.
- return noutput_items;
+ return nout;
}
bool adaptive_dfe_impl::start()
{
+ // make sure python is ready for threading
+ if( Py_IsInitialized() ){
+ GILLock lock;
+ if(PyEval_ThreadsInitialized() != 1 ){
+ PyEval_InitThreads();
+ }
+ boost::python::numpy::initialize();
+ } else {
+ throw std::runtime_error("dont use es_pyhandler without python!");
+ }
+ _taps_samples = (gr_complex*)(volk_malloc( (_nB+_nF+1)*sizeof(gr_complex), volk_get_alignment()));
+ _taps_symbols = (gr_complex*)(volk_malloc( _nW*sizeof(gr_complex), volk_get_alignment()));
+ _hist_samples = (gr_complex*)(volk_malloc(2*(_nB+_nF+1)*sizeof(gr_complex), volk_get_alignment()));
+ _hist_symbols = (gr_complex*)(volk_malloc( 2*_nW*sizeof(gr_complex), volk_get_alignment()));
+ _taps_samples[_nB+1] = 1;
+ _taps_symbols[0] = 1;
+
std::cout << "adaptive_dfe_impl::start()" << std::endl;
GILLock lock;
try {
@@ -137,6 +301,10 @@ bool adaptive_dfe_impl::stop()
std::cout << "adaptive_dfe_impl::stop()" << std::endl;
GILLock lock;
_physicalLayer = boost::python::object();
+ volk_free(_taps_samples);
+ volk_free(_taps_symbols);
+ volk_free(_hist_samples);
+ volk_free(_hist_symbols);
return true;
}
@@ -168,9 +336,11 @@ void adaptive_dfe_impl::update_frame_information(boost::python::object obj)
int const m = array.shape(0);
_symbols.resize(m);
_scramble.resize(m);
+ _descrambled_symbols.resize(m);
for (int i=0; i(obj[1]);
}
@@ -180,7 +350,17 @@ void adaptive_dfe_impl::update_doppler_information(boost::python::object obj)
assert(n==2);
double const do_continue = boost::python::extract(obj[0]);
double const doppler = boost::python::extract(obj[1]);
- // TODO
+
+ float delta_f = doppler/_sps;
+ if (_df == 0) { // init
+ _ud = _df = -delta_f;
+ } else {
+ const float ud_old = _ud;
+ _ud = -delta_f;
+ _df +=_b[0]*_ud + _b[1]*ud_old;
+ }
+ std::cout << "PLL: " << _df << " " << delta_f << std::endl;
+ _sum_phase_diff = 0;
}
} /* namespace digitalhf */
diff --git a/lib/adaptive_dfe_impl.h b/lib/adaptive_dfe_impl.h
index 69b7bf0..28061ac 100644
--- a/lib/adaptive_dfe_impl.h
+++ b/lib/adaptive_dfe_impl.h
@@ -34,19 +34,42 @@ private:
int _sps;
int _nB, _nF, _nW;
+ float _mu;
+ float _alpha;
+
// module name w.r.t. digitalhf.physical_layer containing a PhysicalLayer class
std::string _py_module_name;
boost::python::object _physicalLayer; // class instance of physical layer description
- std::vector _taps_samples;
- std::vector _taps_symbols;
+ gr_complex* _taps_samples;
+ gr_complex* _taps_symbols;
+
+ gr_complex* _hist_samples;
+ gr_complex* _hist_symbols;
+
+ int _hist_sample_index;
+ int _hist_symbol_index;
+
+ std::size_t _sample_counter;
std::vector _constellations;
int _constellation_index;
std::vector _symbols;
std::vector _scramble;
+ std::vector _descrambled_symbols;
+ int _symbol_counter;
- int _sample_counter;
+ // PLL for doppler tracking
+ float _sum_phase_diff;
+ float _df; // frequency offset in radians per sample
+ float _phase; // accumulated phase for frequency correction
+ const float _b[2];
+ float _ud;
+
+ enum state {
+ WAIT_FOR_PREAMBLE,
+ DO_FILTER
+ } _state;
void update_constellations(boost::python::object obj);
void update_frame_information(boost::python::object obj);
diff --git a/python/physical_layer/STANAG_4285.py b/python/physical_layer/STANAG_4285.py
index 5dbc4c4..8bf4cb2 100644
--- a/python/physical_layer/STANAG_4285.py
+++ b/python/physical_layer/STANAG_4285.py
@@ -14,8 +14,9 @@ class PhysicalLayer(object):
self._preamble = [PhysicalLayer.get_preamble(), 0] ## BPSK
self._data = [PhysicalLayer.get_data(), mode] ## according to the mode
self._counter = 0
+ self._preamble_phases = []
- def set_mode(self):
+ def set_mode(self, mode):
"""For STANAG 4258 the mode has to be set manually: mode=0 -> BPSK, mode=1 -> QPSK, mode=2 -> 8PSK"""
self._data[1] = mode
@@ -24,17 +25,32 @@ class PhysicalLayer(object):
def get_frame(self):
"""returns the known+unknown symbols and scrambling"""
+ print('-------------------- get_frame --------------------',self._counter)
if self._counter == 0:
- return self._preamble
+ x= self._preamble
else:
- return self._data
+ x=self._data
+ print('get_frame end\n')
+ return x;
- def get_doppler(self): ## symbols
+ def get_doppler(self, s):
"""used for doppler shift update, for determining which frame to provide next,
and for stopping at end of data/when the signal quality is too low"""
+ print('-------------------- get_doppler --------------------',self._counter)
+ doppler = 0
+ if self._counter == 0: ## preamble
+ corr = s*np.conj(self._preamble[0]['symb'])
+ self._preamble_phases.extend([np.angle(np.sum(corr))])
+ if len(self._preamble_phases) == 2 and False:
+ doppler = 2*(self._preamble_phases[1] - self._preamble_phases[0])/256
+ print('preamble_phases', self._preamble_phases, 'doppler', doppler)
+ self._preamble_phases = self._preamble_phases[1:]
+ else:
+ phases = np.unwrap(np.angle(corr))
+ doppler = 2*(np.median(phases[-20:]) - np.median(phases[:20]))/80
+ print('doppler', doppler,self._preamble_phases)
+
self._counter = (self._counter+1)&1
- ## TODO: doppler calculations
- doppler = 0.1234
return [True, doppler]
@staticmethod
@@ -67,9 +83,9 @@ class PhysicalLayer(object):
## PSK-8 modulation
constellation = PhysicalLayer.make_psk(8,range(8))['points']
a['scramble'] = constellation[p,]
- a['symb'][ 32: 48] = 1 ## mini-probe 1
- a['symb'][ 80: 96] = 1 ## mini-probe 2
- a['symb'][128:144] = 1 ## mini-probe 3
+ a['symb'][ 32: 48] = a['scramble'][ 32: 48] ## mini-probe 1
+ a['symb'][ 80: 96] = a['scramble'][ 80: 96] ## mini-probe 2
+ a['symb'][128:144] = a['scramble'][128:144] ## mini-probe 3
return a
@staticmethod