diff --git a/apps/flowgraphs/fsk9600_ax25.grc b/apps/flowgraphs/fsk9600_ax25.grc
new file mode 100644
index 0000000..4a2c597
--- /dev/null
+++ b/apps/flowgraphs/fsk9600_ax25.grc
@@ -0,0 +1,2969 @@
+
+
+
+ Thu May 5 00:22:45 2016
+
+ options
+
+ author
+ Manolis Surligas (surligas@gmail.com)
+
+
+ window_size
+ 3000, 3000
+
+
+ category
+ Custom
+
+
+ comment
+
+
+
+ description
+ FSK9600 AX.25 decoder with G3RUH support
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (8, 8)
+
+
+ _rotation
+ 0
+
+
+ generate_options
+ no_gui
+
+
+ hier_block_src_path
+ .:
+
+
+ id
+ satnogs_fsk9600_ax25
+
+
+ max_nouts
+ 0
+
+
+ qt_qss_theme
+
+
+
+ realtime_scheduling
+
+
+
+ run_command
+ {python} -u {filename}
+
+
+ run_options
+ run
+
+
+ run
+ True
+
+
+ thread_safe_setters
+
+
+
+ title
+ FSK9600 AX.25 decoder with G3RUH support
+
+
+
+ variable
+
+ comment
+ Decimation factor
+for the RX after the
+SDR received samples
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (911, 1034)
+
+
+ _rotation
+ 0
+
+
+ id
+ audio_gain
+
+
+ value
+ satnogs.fm_demod_settings[rx_sdr_device]['audio_gain']
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (743, 971)
+
+
+ _rotation
+ 0
+
+
+ id
+ audio_samp_rate
+
+
+ value
+ 48000
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (823, 1034)
+
+
+ _rotation
+ 0
+
+
+ id
+ baud_rate
+
+
+ value
+ 9600
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (743, 1034)
+
+
+ _rotation
+ 0
+
+
+ id
+ deviation
+
+
+ value
+ 5000
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1014, 971)
+
+
+ _rotation
+ 0
+
+
+ id
+ filter_rate
+
+
+ value
+ 250000
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1014, 1034)
+
+
+ _rotation
+ 0
+
+
+ id
+ modulation_index
+
+
+ value
+ deviation / (baud_rate / 2.0)
+
+
+
+ variable
+
+ comment
+ SDR device
+TX sampling rate
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (743, 843)
+
+
+ _rotation
+ 0
+
+
+ id
+ samp_rate_rx
+
+
+ value
+ satnogs.hw_rx_settings[rx_sdr_device]['samp_rate']
+
+
+
+ variable_low_pass_filter_taps
+
+ beta
+ 6.76
+
+
+ comment
+
+
+
+ cutoff_freq
+ 100e3
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (48, 716)
+
+
+ _rotation
+ 0
+
+
+ gain
+ 12.0
+
+
+ id
+ taps
+
+
+ samp_rate
+ samp_rate_rx
+
+
+ width
+ 60000
+
+
+ win
+ firdes.WIN_HAMMING
+
+
+
+ variable
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (863, 971)
+
+
+ _rotation
+ 0
+
+
+ id
+ xlate_filter_taps
+
+
+ value
+ firdes.low_pass(1, samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76)
+
+
+
+ analog_quadrature_demod_cf
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1046, 339)
+
+
+ _rotation
+ 180
+
+
+ gain
+ ((audio_samp_rate) / baud_rate)/(math.pi*modulation_index)
+
+
+ id
+ analog_quadrature_demod_cf_0_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+
+ rational_resampler_xxx
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ decim
+ 125
+
+
+ _enabled
+ True
+
+
+ fbw
+ 0
+
+
+ _coordinate
+ (1272, 268)
+
+
+ _rotation
+ 0
+
+
+ id
+ blks2_rational_resampler_xxx_1
+
+
+ interp
+ 24
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ taps
+ []
+
+
+ type
+ ccc
+
+
+
+ blocks_file_sink
+
+ append
+ False
+
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ file
+ /tmp/iq.dat
+
+
+ _coordinate
+ (1270, 171)
+
+
+ _rotation
+ 0
+
+
+ id
+ blocks_file_sink_0
+
+
+ type
+ complex
+
+
+ unbuffered
+ False
+
+
+ vlen
+ 1
+
+
+
+ dc_blocker_xx
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (855, 427)
+
+
+ _rotation
+ 0
+
+
+ id
+ dc_blocker_xx_0
+
+
+ length
+ 1024
+
+
+ long_form
+ True
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ type
+ ff
+
+
+
+ digital_binary_slicer_fb
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (1526, 439)
+
+
+ _rotation
+ 0
+
+
+ id
+ digital_binary_slicer_fb_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+
+ digital_clock_recovery_mm_xx
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (1262, 407)
+
+
+ _rotation
+ 0
+
+
+ gain_mu
+ 0.175
+
+
+ gain_omega
+ 0.25*0.175*0.175
+
+
+ id
+ digital_clock_recovery_mm_xx_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ mu
+ 0.5
+
+
+ omega_relative_limit
+ 0.005
+
+
+ omega
+ 48e3/9600
+
+
+ type
+ float
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (64, 984)
+
+
+ _rotation
+ 0
+
+
+ id
+ doppler_correction_per_sec
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ intx
+
+
+ value
+ 1000
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (743, 755)
+
+
+ _rotation
+ 180
+
+
+ id
+ file_path
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ string
+
+
+ value
+ test.wav
+
+
+
+ freq_xlating_fir_filter_xxx
+
+ alias
+
+
+
+ center_freq
+ lo_offset
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ decim
+ int(samp_rate_rx/filter_rate)
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (680, 268)
+
+
+ _rotation
+ 0
+
+
+ id
+ freq_xlating_fir_filter_xxx_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ samp_rate
+ samp_rate_rx
+
+
+ taps
+ xlate_filter_taps
+
+
+ type
+ ccc
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+ To avoid the SDR carrier at the DC
+we shift the LO a little further
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (863, 843)
+
+
+ _rotation
+ 0
+
+
+ id
+ lo_offset
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ eng_float
+
+
+ value
+ 100e3
+
+
+
+ low_pass_filter
+
+ beta
+ 6.76
+
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ cutoff_freq
+ 7850
+
+
+ decim
+ 1
+
+
+ _enabled
+ True
+
+
+ type
+ fir_filter_fff
+
+
+ _coordinate
+ (1054, 391)
+
+
+ _rotation
+ 0
+
+
+ gain
+ 1
+
+
+ id
+ low_pass_filter_0
+
+
+ interp
+ 1
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ samp_rate
+ audio_samp_rate
+
+
+ width
+ 0.15
+
+
+ win
+ firdes.WIN_HAMMING
+
+
+
+ osmosdr_source
+
+ alias
+
+
+
+ ant0
+ satnogs.hw_rx_settings[rx_sdr_device]['antenna']
+
+
+ bb_gain0
+ satnogs.hw_rx_settings[rx_sdr_device]['bb_gain']
+
+
+ bw0
+ samp_rate_rx
+
+
+ dc_offset_mode0
+ 2
+
+
+ corr0
+ ppm
+
+
+ freq0
+ rx_freq - lo_offset
+
+
+ gain_mode0
+ False
+
+
+ if_gain0
+ satnogs.hw_rx_settings[rx_sdr_device]['if_gain']
+
+
+ iq_balance_mode0
+ 0
+
+
+ gain0
+ satnogs.hw_rx_settings[rx_sdr_device]['rf_gain']
+
+
+ ant10
+
+
+
+ bb_gain10
+ 20
+
+
+ bw10
+ 0
+
+
+ dc_offset_mode10
+ 0
+
+
+ corr10
+ 0
+
+
+ freq10
+ 100e6
+
+
+ gain_mode10
+ False
+
+
+ if_gain10
+ 20
+
+
+ iq_balance_mode10
+ 0
+
+
+ gain10
+ 10
+
+
+ ant11
+
+
+
+ bb_gain11
+ 20
+
+
+ bw11
+ 0
+
+
+ dc_offset_mode11
+ 0
+
+
+ corr11
+ 0
+
+
+ freq11
+ 100e6
+
+
+ gain_mode11
+ False
+
+
+ if_gain11
+ 20
+
+
+ iq_balance_mode11
+ 0
+
+
+ gain11
+ 10
+
+
+ ant12
+
+
+
+ bb_gain12
+ 20
+
+
+ bw12
+ 0
+
+
+ dc_offset_mode12
+ 0
+
+
+ corr12
+ 0
+
+
+ freq12
+ 100e6
+
+
+ gain_mode12
+ False
+
+
+ if_gain12
+ 20
+
+
+ iq_balance_mode12
+ 0
+
+
+ gain12
+ 10
+
+
+ ant13
+
+
+
+ bb_gain13
+ 20
+
+
+ bw13
+ 0
+
+
+ dc_offset_mode13
+ 0
+
+
+ corr13
+ 0
+
+
+ freq13
+ 100e6
+
+
+ gain_mode13
+ False
+
+
+ if_gain13
+ 20
+
+
+ iq_balance_mode13
+ 0
+
+
+ gain13
+ 10
+
+
+ ant14
+
+
+
+ bb_gain14
+ 20
+
+
+ bw14
+ 0
+
+
+ dc_offset_mode14
+ 0
+
+
+ corr14
+ 0
+
+
+ freq14
+ 100e6
+
+
+ gain_mode14
+ False
+
+
+ if_gain14
+ 20
+
+
+ iq_balance_mode14
+ 0
+
+
+ gain14
+ 10
+
+
+ ant15
+
+
+
+ bb_gain15
+ 20
+
+
+ bw15
+ 0
+
+
+ dc_offset_mode15
+ 0
+
+
+ corr15
+ 0
+
+
+ freq15
+ 100e6
+
+
+ gain_mode15
+ False
+
+
+ if_gain15
+ 20
+
+
+ iq_balance_mode15
+ 0
+
+
+ gain15
+ 10
+
+
+ ant16
+
+
+
+ bb_gain16
+ 20
+
+
+ bw16
+ 0
+
+
+ dc_offset_mode16
+ 0
+
+
+ corr16
+ 0
+
+
+ freq16
+ 100e6
+
+
+ gain_mode16
+ False
+
+
+ if_gain16
+ 20
+
+
+ iq_balance_mode16
+ 0
+
+
+ gain16
+ 10
+
+
+ ant17
+
+
+
+ bb_gain17
+ 20
+
+
+ bw17
+ 0
+
+
+ dc_offset_mode17
+ 0
+
+
+ corr17
+ 0
+
+
+ freq17
+ 100e6
+
+
+ gain_mode17
+ False
+
+
+ if_gain17
+ 20
+
+
+ iq_balance_mode17
+ 0
+
+
+ gain17
+ 10
+
+
+ ant18
+
+
+
+ bb_gain18
+ 20
+
+
+ bw18
+ 0
+
+
+ dc_offset_mode18
+ 0
+
+
+ corr18
+ 0
+
+
+ freq18
+ 100e6
+
+
+ gain_mode18
+ False
+
+
+ if_gain18
+ 20
+
+
+ iq_balance_mode18
+ 0
+
+
+ gain18
+ 10
+
+
+ ant19
+
+
+
+ bb_gain19
+ 20
+
+
+ bw19
+ 0
+
+
+ dc_offset_mode19
+ 0
+
+
+ corr19
+ 0
+
+
+ freq19
+ 100e6
+
+
+ gain_mode19
+ False
+
+
+ if_gain19
+ 20
+
+
+ iq_balance_mode19
+ 0
+
+
+ gain19
+ 10
+
+
+ ant1
+
+
+
+ bb_gain1
+ 20
+
+
+ bw1
+ 0
+
+
+ dc_offset_mode1
+ 0
+
+
+ corr1
+ 0
+
+
+ freq1
+ 100e6
+
+
+ gain_mode1
+ False
+
+
+ if_gain1
+ 20
+
+
+ iq_balance_mode1
+ 0
+
+
+ gain1
+ 10
+
+
+ ant20
+
+
+
+ bb_gain20
+ 20
+
+
+ bw20
+ 0
+
+
+ dc_offset_mode20
+ 0
+
+
+ corr20
+ 0
+
+
+ freq20
+ 100e6
+
+
+ gain_mode20
+ False
+
+
+ if_gain20
+ 20
+
+
+ iq_balance_mode20
+ 0
+
+
+ gain20
+ 10
+
+
+ ant21
+
+
+
+ bb_gain21
+ 20
+
+
+ bw21
+ 0
+
+
+ dc_offset_mode21
+ 0
+
+
+ corr21
+ 0
+
+
+ freq21
+ 100e6
+
+
+ gain_mode21
+ False
+
+
+ if_gain21
+ 20
+
+
+ iq_balance_mode21
+ 0
+
+
+ gain21
+ 10
+
+
+ ant22
+
+
+
+ bb_gain22
+ 20
+
+
+ bw22
+ 0
+
+
+ dc_offset_mode22
+ 0
+
+
+ corr22
+ 0
+
+
+ freq22
+ 100e6
+
+
+ gain_mode22
+ False
+
+
+ if_gain22
+ 20
+
+
+ iq_balance_mode22
+ 0
+
+
+ gain22
+ 10
+
+
+ ant23
+
+
+
+ bb_gain23
+ 20
+
+
+ bw23
+ 0
+
+
+ dc_offset_mode23
+ 0
+
+
+ corr23
+ 0
+
+
+ freq23
+ 100e6
+
+
+ gain_mode23
+ False
+
+
+ if_gain23
+ 20
+
+
+ iq_balance_mode23
+ 0
+
+
+ gain23
+ 10
+
+
+ ant24
+
+
+
+ bb_gain24
+ 20
+
+
+ bw24
+ 0
+
+
+ dc_offset_mode24
+ 0
+
+
+ corr24
+ 0
+
+
+ freq24
+ 100e6
+
+
+ gain_mode24
+ False
+
+
+ if_gain24
+ 20
+
+
+ iq_balance_mode24
+ 0
+
+
+ gain24
+ 10
+
+
+ ant25
+
+
+
+ bb_gain25
+ 20
+
+
+ bw25
+ 0
+
+
+ dc_offset_mode25
+ 0
+
+
+ corr25
+ 0
+
+
+ freq25
+ 100e6
+
+
+ gain_mode25
+ False
+
+
+ if_gain25
+ 20
+
+
+ iq_balance_mode25
+ 0
+
+
+ gain25
+ 10
+
+
+ ant26
+
+
+
+ bb_gain26
+ 20
+
+
+ bw26
+ 0
+
+
+ dc_offset_mode26
+ 0
+
+
+ corr26
+ 0
+
+
+ freq26
+ 100e6
+
+
+ gain_mode26
+ False
+
+
+ if_gain26
+ 20
+
+
+ iq_balance_mode26
+ 0
+
+
+ gain26
+ 10
+
+
+ ant27
+
+
+
+ bb_gain27
+ 20
+
+
+ bw27
+ 0
+
+
+ dc_offset_mode27
+ 0
+
+
+ corr27
+ 0
+
+
+ freq27
+ 100e6
+
+
+ gain_mode27
+ False
+
+
+ if_gain27
+ 20
+
+
+ iq_balance_mode27
+ 0
+
+
+ gain27
+ 10
+
+
+ ant28
+
+
+
+ bb_gain28
+ 20
+
+
+ bw28
+ 0
+
+
+ dc_offset_mode28
+ 0
+
+
+ corr28
+ 0
+
+
+ freq28
+ 100e6
+
+
+ gain_mode28
+ False
+
+
+ if_gain28
+ 20
+
+
+ iq_balance_mode28
+ 0
+
+
+ gain28
+ 10
+
+
+ ant29
+
+
+
+ bb_gain29
+ 20
+
+
+ bw29
+ 0
+
+
+ dc_offset_mode29
+ 0
+
+
+ corr29
+ 0
+
+
+ freq29
+ 100e6
+
+
+ gain_mode29
+ False
+
+
+ if_gain29
+ 20
+
+
+ iq_balance_mode29
+ 0
+
+
+ gain29
+ 10
+
+
+ ant2
+
+
+
+ bb_gain2
+ 20
+
+
+ bw2
+ 0
+
+
+ dc_offset_mode2
+ 0
+
+
+ corr2
+ 0
+
+
+ freq2
+ 100e6
+
+
+ gain_mode2
+ False
+
+
+ if_gain2
+ 20
+
+
+ iq_balance_mode2
+ 0
+
+
+ gain2
+ 10
+
+
+ ant30
+
+
+
+ bb_gain30
+ 20
+
+
+ bw30
+ 0
+
+
+ dc_offset_mode30
+ 0
+
+
+ corr30
+ 0
+
+
+ freq30
+ 100e6
+
+
+ gain_mode30
+ False
+
+
+ if_gain30
+ 20
+
+
+ iq_balance_mode30
+ 0
+
+
+ gain30
+ 10
+
+
+ ant31
+
+
+
+ bb_gain31
+ 20
+
+
+ bw31
+ 0
+
+
+ dc_offset_mode31
+ 0
+
+
+ corr31
+ 0
+
+
+ freq31
+ 100e6
+
+
+ gain_mode31
+ False
+
+
+ if_gain31
+ 20
+
+
+ iq_balance_mode31
+ 0
+
+
+ gain31
+ 10
+
+
+ ant3
+
+
+
+ bb_gain3
+ 20
+
+
+ bw3
+ 0
+
+
+ dc_offset_mode3
+ 0
+
+
+ corr3
+ 0
+
+
+ freq3
+ 100e6
+
+
+ gain_mode3
+ False
+
+
+ if_gain3
+ 20
+
+
+ iq_balance_mode3
+ 0
+
+
+ gain3
+ 10
+
+
+ ant4
+
+
+
+ bb_gain4
+ 20
+
+
+ bw4
+ 0
+
+
+ dc_offset_mode4
+ 0
+
+
+ corr4
+ 0
+
+
+ freq4
+ 100e6
+
+
+ gain_mode4
+ False
+
+
+ if_gain4
+ 20
+
+
+ iq_balance_mode4
+ 0
+
+
+ gain4
+ 10
+
+
+ ant5
+
+
+
+ bb_gain5
+ 20
+
+
+ bw5
+ 0
+
+
+ dc_offset_mode5
+ 0
+
+
+ corr5
+ 0
+
+
+ freq5
+ 100e6
+
+
+ gain_mode5
+ False
+
+
+ if_gain5
+ 20
+
+
+ iq_balance_mode5
+ 0
+
+
+ gain5
+ 10
+
+
+ ant6
+
+
+
+ bb_gain6
+ 20
+
+
+ bw6
+ 0
+
+
+ dc_offset_mode6
+ 0
+
+
+ corr6
+ 0
+
+
+ freq6
+ 100e6
+
+
+ gain_mode6
+ False
+
+
+ if_gain6
+ 20
+
+
+ iq_balance_mode6
+ 0
+
+
+ gain6
+ 10
+
+
+ ant7
+
+
+
+ bb_gain7
+ 20
+
+
+ bw7
+ 0
+
+
+ dc_offset_mode7
+ 0
+
+
+ corr7
+ 0
+
+
+ freq7
+ 100e6
+
+
+ gain_mode7
+ False
+
+
+ if_gain7
+ 20
+
+
+ iq_balance_mode7
+ 0
+
+
+ gain7
+ 10
+
+
+ ant8
+
+
+
+ bb_gain8
+ 20
+
+
+ bw8
+ 0
+
+
+ dc_offset_mode8
+ 0
+
+
+ corr8
+ 0
+
+
+ freq8
+ 100e6
+
+
+ gain_mode8
+ False
+
+
+ if_gain8
+ 20
+
+
+ iq_balance_mode8
+ 0
+
+
+ gain8
+ 10
+
+
+ ant9
+
+
+
+ bb_gain9
+ 20
+
+
+ bw9
+ 0
+
+
+ dc_offset_mode9
+ 0
+
+
+ corr9
+ 0
+
+
+ freq9
+ 100e6
+
+
+ gain_mode9
+ False
+
+
+ if_gain9
+ 20
+
+
+ iq_balance_mode9
+ 0
+
+
+ gain9
+ 10
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ args
+ satnogs.hw_rx_settings[rx_sdr_device]['dev_arg']
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (16, 376)
+
+
+ _rotation
+ 0
+
+
+ id
+ osmosdr_source_0
+
+
+ maxoutbuf
+ 0
+
+
+ clock_source0
+
+
+
+ time_source0
+
+
+
+ clock_source1
+
+
+
+ time_source1
+
+
+
+ clock_source2
+
+
+
+ time_source2
+
+
+
+ clock_source3
+
+
+
+ time_source3
+
+
+
+ clock_source4
+
+
+
+ time_source4
+
+
+
+ clock_source5
+
+
+
+ time_source5
+
+
+
+ clock_source6
+
+
+
+ time_source6
+
+
+
+ clock_source7
+
+
+
+ time_source7
+
+
+
+ minoutbuf
+ 0
+
+
+ nchan
+ 1
+
+
+ num_mboards
+ 1
+
+
+ type
+ fc32
+
+
+ sample_rate
+ samp_rate_rx
+
+
+ sync
+
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (975, 755)
+
+
+ _rotation
+ 0
+
+
+ id
+ ppm
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ intx
+
+
+ value
+ 0
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1054, 755)
+
+
+ _rotation
+ 0
+
+
+ id
+ rigctl_port
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ intx
+
+
+ value
+ 4532
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (959, 843)
+
+
+ _rotation
+ 0
+
+
+ id
+ rx_freq
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ eng_float
+
+
+ value
+ 100e6
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (312, 984)
+
+
+ _rotation
+ 0
+
+
+ id
+ rx_sdr_device
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ string
+
+
+ value
+ usrpb200
+
+
+
+ satnogs_ax25_decoder_bm
+
+ n_sync_flags
+ 3
+
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ descrambling
+ True
+
+
+ _coordinate
+ (1374, 543)
+
+
+ _rotation
+ 180
+
+
+ id
+ satnogs_ax25_decoder_bm_0
+
+
+ maxoutbuf
+ 0
+
+
+ max_frame_len
+ 1024
+
+
+ minoutbuf
+ 0
+
+
+ promisc
+ True
+
+
+ addr
+ 'GND'
+
+
+ ssid
+ 0
+
+
+
+ satnogs_coarse_doppler_correction_cc
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (352, 276)
+
+
+ _rotation
+ 0
+
+
+ id
+ satnogs_coarse_doppler_correction_cc_0
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ sampling_rate
+ samp_rate_rx
+
+
+ target_freq
+ rx_freq
+
+
+
+ satnogs_multi_format_msg_sink
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1030, 579)
+
+
+ _rotation
+ 180
+
+
+ id
+ satnogs_multi_format_msg_sink_0
+
+
+ format
+ 1
+
+
+
+ satnogs_multi_format_msg_sink
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (1030, 631)
+
+
+ _rotation
+ 180
+
+
+ id
+ satnogs_multi_format_msg_sink_0_0
+
+
+ format
+ 1
+
+
+
+ satnogs_ogg_encoder
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ filename
+ file_path
+
+
+ _coordinate
+ (831, 499)
+
+
+ _rotation
+ 180
+
+
+ id
+ satnogs_ogg_encoder_0
+
+
+ quality
+ 1.0
+
+
+ samp_rate
+ audio_samp_rate
+
+
+
+ satnogs_tcp_rigctl_msg_source
+
+ alias
+
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ 1
+
+
+ _coordinate
+ (16, 204)
+
+
+ _rotation
+ 0
+
+
+ id
+ satnogs_tcp_rigctl_msg_source_0
+
+
+ addr
+ "127.0.0.1"
+
+
+ mtu
+ 1500
+
+
+ maxoutbuf
+ 0
+
+
+ minoutbuf
+ 0
+
+
+ mode
+ False
+
+
+ port
+ rigctl_port
+
+
+ interval
+ 1000
+
+
+
+ satnogs_waterfall_sink
+
+ alias
+
+
+
+ center_freq
+ 0.0
+
+
+ comment
+
+
+
+ affinity
+
+
+
+ _enabled
+ True
+
+
+ fft_size
+ 1024
+
+
+ filename
+ waterfall_file_path
+
+
+ _coordinate
+ (1486, 255)
+
+
+ _rotation
+ 0
+
+
+ id
+ satnogs_waterfall_sink_0
+
+
+ mode
+ 1
+
+
+ pps
+ 8
+
+
+ samp_rate
+ audio_samp_rate
+
+
+
+ parameter
+
+ alias
+
+
+
+ comment
+
+
+
+ _enabled
+ True
+
+
+ _coordinate
+ (839, 755)
+
+
+ _rotation
+ 0
+
+
+ id
+ waterfall_file_path
+
+
+ label
+
+
+
+ short_id
+
+
+
+ type
+ string
+
+
+ value
+ /tmp/waterfall.dat
+
+
+
+ analog_quadrature_demod_cf_0_0
+ dc_blocker_xx_0
+ 0
+ 0
+
+
+ blks2_rational_resampler_xxx_1
+ analog_quadrature_demod_cf_0_0
+ 0
+ 0
+
+
+ blks2_rational_resampler_xxx_1
+ blocks_file_sink_0
+ 0
+ 0
+
+
+ blks2_rational_resampler_xxx_1
+ satnogs_waterfall_sink_0
+ 0
+ 0
+
+
+ dc_blocker_xx_0
+ low_pass_filter_0
+ 0
+ 0
+
+
+ digital_binary_slicer_fb_0
+ satnogs_ax25_decoder_bm_0
+ 0
+ 0
+
+
+ digital_clock_recovery_mm_xx_0
+ digital_binary_slicer_fb_0
+ 0
+ 0
+
+
+ freq_xlating_fir_filter_xxx_0
+ blks2_rational_resampler_xxx_1
+ 0
+ 0
+
+
+ low_pass_filter_0
+ digital_clock_recovery_mm_xx_0
+ 0
+ 0
+
+
+ low_pass_filter_0
+ satnogs_ogg_encoder_0
+ 0
+ 0
+
+
+ osmosdr_source_0
+ satnogs_coarse_doppler_correction_cc_0
+ 0
+ 0
+
+
+ satnogs_ax25_decoder_bm_0
+ satnogs_multi_format_msg_sink_0
+ failed_pdu
+ in
+
+
+ satnogs_ax25_decoder_bm_0
+ satnogs_multi_format_msg_sink_0_0
+ pdu
+ in
+
+
+ satnogs_coarse_doppler_correction_cc_0
+ freq_xlating_fir_filter_xxx_0
+ 0
+ 0
+
+
+ satnogs_tcp_rigctl_msg_source_0
+ satnogs_coarse_doppler_correction_cc_0
+ freq
+ freq
+
+
diff --git a/apps/flowgraphs/satnogs_fsk9600_ax25.py b/apps/flowgraphs/satnogs_fsk9600_ax25.py
new file mode 100755
index 0000000..eb740e9
--- /dev/null
+++ b/apps/flowgraphs/satnogs_fsk9600_ax25.py
@@ -0,0 +1,280 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+##################################################
+# GNU Radio Python Flow Graph
+# Title: FSK9600 AX.25 decoder with G3RUH support
+# Author: Manolis Surligas (surligas@gmail.com)
+# Description: FSK9600 AX.25 decoder with G3RUH support
+# Generated: Sun Jul 30 00:21:32 2017
+##################################################
+
+from gnuradio import analog
+from gnuradio import blocks
+from gnuradio import digital
+from gnuradio import eng_notation
+from gnuradio import filter
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from gnuradio.filter import firdes
+from optparse import OptionParser
+import math
+import osmosdr
+import satnogs
+import time
+
+
+class satnogs_fsk9600_ax25(gr.top_block):
+
+ def __init__(self, doppler_correction_per_sec=1000, file_path='test.wav', lo_offset=100e3, ppm=0, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', waterfall_file_path='/tmp/waterfall.dat'):
+ gr.top_block.__init__(self, "FSK9600 AX.25 decoder with G3RUH support")
+
+ ##################################################
+ # Parameters
+ ##################################################
+ self.doppler_correction_per_sec = doppler_correction_per_sec
+ self.file_path = file_path
+ self.lo_offset = lo_offset
+ self.ppm = ppm
+ self.rigctl_port = rigctl_port
+ self.rx_freq = rx_freq
+ self.rx_sdr_device = rx_sdr_device
+ self.waterfall_file_path = waterfall_file_path
+
+ ##################################################
+ # Variables
+ ##################################################
+ self.samp_rate_rx = samp_rate_rx = satnogs.hw_rx_settings[rx_sdr_device]['samp_rate']
+ self.deviation = deviation = 5000
+ self.baud_rate = baud_rate = 9600
+ self.xlate_filter_taps = xlate_filter_taps = firdes.low_pass(1, samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76)
+
+ self.taps = taps = firdes.low_pass(12.0, samp_rate_rx, 100e3, 60000, firdes.WIN_HAMMING, 6.76)
+
+ self.modulation_index = modulation_index = deviation / (baud_rate / 2.0)
+ self.filter_rate = filter_rate = 250000
+ self.audio_samp_rate = audio_samp_rate = 48000
+ self.audio_gain = audio_gain = satnogs.fm_demod_settings[rx_sdr_device]['audio_gain']
+
+ ##################################################
+ # Blocks
+ ##################################################
+ self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 8, 1024, waterfall_file_path, 1)
+ self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500)
+ self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0)
+ self.satnogs_multi_format_msg_sink_0_0 = satnogs.multi_format_msg_sink(1)
+ self.satnogs_multi_format_msg_sink_0 = satnogs.multi_format_msg_sink(1)
+ self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx)
+ self.satnogs_ax25_decoder_bm_0 = satnogs.ax25_decoder_bm('GND', 0, True, True, 1024, 3)
+ self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] )
+ self.osmosdr_source_0.set_sample_rate(samp_rate_rx)
+ self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0)
+ self.osmosdr_source_0.set_freq_corr(ppm, 0)
+ self.osmosdr_source_0.set_dc_offset_mode(2, 0)
+ self.osmosdr_source_0.set_iq_balance_mode(0, 0)
+ self.osmosdr_source_0.set_gain_mode(False, 0)
+ self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0)
+ self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[rx_sdr_device]['if_gain'], 0)
+ self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'], 0)
+ self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[rx_sdr_device]['antenna'], 0)
+ self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0)
+
+ self.low_pass_filter_0 = filter.fir_filter_fff(1, firdes.low_pass(
+ 1, audio_samp_rate, 7850, 0.15, firdes.WIN_HAMMING, 6.76))
+ self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(int(samp_rate_rx/filter_rate), (xlate_filter_taps), lo_offset, samp_rate_rx)
+ self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(48e3/9600, 0.25*0.175*0.175, 0.5, 0.175, 0.005)
+ self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb()
+ self.dc_blocker_xx_0 = filter.dc_blocker_ff(1024, True)
+ self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_gr_complex*1, '/tmp/iq.dat', False)
+ self.blocks_file_sink_0.set_unbuffered(False)
+ self.blks2_rational_resampler_xxx_1 = filter.rational_resampler_ccc(
+ interpolation=24,
+ decimation=125,
+ taps=None,
+ fractional_bw=None,
+ )
+ self.analog_quadrature_demod_cf_0_0 = analog.quadrature_demod_cf(((audio_samp_rate) / baud_rate)/(math.pi*modulation_index))
+
+ ##################################################
+ # Connections
+ ##################################################
+ self.msg_connect((self.satnogs_ax25_decoder_bm_0, 'failed_pdu'), (self.satnogs_multi_format_msg_sink_0, 'in'))
+ self.msg_connect((self.satnogs_ax25_decoder_bm_0, 'pdu'), (self.satnogs_multi_format_msg_sink_0_0, 'in'))
+ self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq'))
+ self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.dc_blocker_xx_0, 0))
+ self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.analog_quadrature_demod_cf_0_0, 0))
+ self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.blocks_file_sink_0, 0))
+ self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.satnogs_waterfall_sink_0, 0))
+ self.connect((self.dc_blocker_xx_0, 0), (self.low_pass_filter_0, 0))
+ self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_ax25_decoder_bm_0, 0))
+ self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0))
+ self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blks2_rational_resampler_xxx_1, 0))
+ self.connect((self.low_pass_filter_0, 0), (self.digital_clock_recovery_mm_xx_0, 0))
+ self.connect((self.low_pass_filter_0, 0), (self.satnogs_ogg_encoder_0, 0))
+ self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0))
+ self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0))
+
+ def get_doppler_correction_per_sec(self):
+ return self.doppler_correction_per_sec
+
+ def set_doppler_correction_per_sec(self, doppler_correction_per_sec):
+ self.doppler_correction_per_sec = doppler_correction_per_sec
+
+ def get_file_path(self):
+ return self.file_path
+
+ def set_file_path(self, file_path):
+ self.file_path = file_path
+
+ def get_lo_offset(self):
+ return self.lo_offset
+
+ def set_lo_offset(self, lo_offset):
+ self.lo_offset = lo_offset
+ self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0)
+ self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset)
+
+ def get_ppm(self):
+ return self.ppm
+
+ def set_ppm(self, ppm):
+ self.ppm = ppm
+ self.osmosdr_source_0.set_freq_corr(self.ppm, 0)
+
+ def get_rigctl_port(self):
+ return self.rigctl_port
+
+ def set_rigctl_port(self, rigctl_port):
+ self.rigctl_port = rigctl_port
+
+ def get_rx_freq(self):
+ return self.rx_freq
+
+ def set_rx_freq(self, rx_freq):
+ self.rx_freq = rx_freq
+ self.satnogs_coarse_doppler_correction_cc_0.set_new_freq_locked(self.rx_freq)
+ self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0)
+
+ def get_rx_sdr_device(self):
+ return self.rx_sdr_device
+
+ def set_rx_sdr_device(self, rx_sdr_device):
+ self.rx_sdr_device = rx_sdr_device
+ self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate'])
+ self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0)
+ self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0)
+ self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0)
+ self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0)
+ self.set_audio_gain(satnogs.fm_demod_settings[self.rx_sdr_device]['audio_gain'])
+
+ def get_waterfall_file_path(self):
+ return self.waterfall_file_path
+
+ def set_waterfall_file_path(self, waterfall_file_path):
+ self.waterfall_file_path = waterfall_file_path
+
+ def get_samp_rate_rx(self):
+ return self.samp_rate_rx
+
+ def set_samp_rate_rx(self, samp_rate_rx):
+ self.samp_rate_rx = samp_rate_rx
+ self.set_xlate_filter_taps(firdes.low_pass(1, self.samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76))
+ self.osmosdr_source_0.set_sample_rate(self.samp_rate_rx)
+ self.osmosdr_source_0.set_bandwidth(self.samp_rate_rx, 0)
+
+ def get_deviation(self):
+ return self.deviation
+
+ def set_deviation(self, deviation):
+ self.deviation = deviation
+ self.set_modulation_index(self.deviation / (self.baud_rate / 2.0))
+
+ def get_baud_rate(self):
+ return self.baud_rate
+
+ def set_baud_rate(self, baud_rate):
+ self.baud_rate = baud_rate
+ self.set_modulation_index(self.deviation / (self.baud_rate / 2.0))
+ self.analog_quadrature_demod_cf_0_0.set_gain(((self.audio_samp_rate) / self.baud_rate)/(math.pi*self.modulation_index))
+
+ def get_xlate_filter_taps(self):
+ return self.xlate_filter_taps
+
+ def set_xlate_filter_taps(self, xlate_filter_taps):
+ self.xlate_filter_taps = xlate_filter_taps
+ self.freq_xlating_fir_filter_xxx_0.set_taps((self.xlate_filter_taps))
+
+ def get_taps(self):
+ return self.taps
+
+ def set_taps(self, taps):
+ self.taps = taps
+
+ def get_modulation_index(self):
+ return self.modulation_index
+
+ def set_modulation_index(self, modulation_index):
+ self.modulation_index = modulation_index
+ self.analog_quadrature_demod_cf_0_0.set_gain(((self.audio_samp_rate) / self.baud_rate)/(math.pi*self.modulation_index))
+
+ def get_filter_rate(self):
+ return self.filter_rate
+
+ def set_filter_rate(self, filter_rate):
+ self.filter_rate = filter_rate
+
+ def get_audio_samp_rate(self):
+ return self.audio_samp_rate
+
+ def set_audio_samp_rate(self, audio_samp_rate):
+ self.audio_samp_rate = audio_samp_rate
+ self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 7850, 0.15, firdes.WIN_HAMMING, 6.76))
+ self.analog_quadrature_demod_cf_0_0.set_gain(((self.audio_samp_rate) / self.baud_rate)/(math.pi*self.modulation_index))
+
+ def get_audio_gain(self):
+ return self.audio_gain
+
+ def set_audio_gain(self, audio_gain):
+ self.audio_gain = audio_gain
+
+
+def argument_parser():
+ description = 'FSK9600 AX.25 decoder with G3RUH support'
+ parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description)
+ parser.add_option(
+ "", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=1000,
+ help="Set doppler_correction_per_sec [default=%default]")
+ parser.add_option(
+ "", "--file-path", dest="file_path", type="string", default='test.wav',
+ help="Set file_path [default=%default]")
+ parser.add_option(
+ "", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3),
+ help="Set lo_offset [default=%default]")
+ parser.add_option(
+ "", "--ppm", dest="ppm", type="intx", default=0,
+ help="Set ppm [default=%default]")
+ parser.add_option(
+ "", "--rigctl-port", dest="rigctl_port", type="intx", default=4532,
+ help="Set rigctl_port [default=%default]")
+ parser.add_option(
+ "", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6),
+ help="Set rx_freq [default=%default]")
+ parser.add_option(
+ "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200',
+ help="Set rx_sdr_device [default=%default]")
+ parser.add_option(
+ "", "--waterfall-file-path", dest="waterfall_file_path", type="string", default='/tmp/waterfall.dat',
+ help="Set waterfall_file_path [default=%default]")
+ return parser
+
+
+def main(top_block_cls=satnogs_fsk9600_ax25, options=None):
+ if options is None:
+ options, _ = argument_parser().parse_args()
+
+ tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, ppm=options.ppm, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, waterfall_file_path=options.waterfall_file_path)
+ tb.start()
+ tb.wait()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/include/satnogs/ax25_decoder_bm.h b/include/satnogs/ax25_decoder_bm.h
index bcf4d7d..3bd1480 100644
--- a/include/satnogs/ax25_decoder_bm.h
+++ b/include/satnogs/ax25_decoder_bm.h
@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
- * Copyright (C) 2016, Libre Space Foundation
+ * Copyright (C) 2016, 2017
+ * Libre Space Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/lib/ax25_decoder_bm_impl.cc b/lib/ax25_decoder_bm_impl.cc
index d11507d..a154eea 100644
--- a/lib/ax25_decoder_bm_impl.cc
+++ b/lib/ax25_decoder_bm_impl.cc
@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
- * Copyright (C) 2016, Libre Space Foundation
+ * Copyright (C) 2016, 2017
+ * Libre Space Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,41 +35,40 @@ namespace gr
ax25_decoder_bm::sptr
ax25_decoder_bm::make (const std::string& addr, uint8_t ssid, bool promisc,
- bool descramble, size_t max_frame_len,
- size_t n_sync_flags)
+ bool descramble, size_t max_frame_len,
+ size_t n_sync_flags)
{
return gnuradio::get_initial_sptr (
- new ax25_decoder_bm_impl (addr, ssid, promisc,
- descramble, max_frame_len,
- n_sync_flags));
+ new ax25_decoder_bm_impl (addr, ssid, promisc, descramble,
+ max_frame_len, n_sync_flags));
}
/*
* The private constructor
*/
ax25_decoder_bm_impl::ax25_decoder_bm_impl (const std::string& addr,
- uint8_t ssid, bool promisc,
- bool descramble,
- size_t max_frame_len,
- size_t n_sync_flags) :
- gr::sync_block ("ax25_decoder_bm",
- gr::io_signature::make (1, 1, sizeof(uint8_t)),
- gr::io_signature::make (0, 0, 0)),
- d_promisc (promisc),
- d_descramble (descramble),
- d_max_frame_len (max_frame_len),
- d_sync_flags_thr (n_sync_flags - 1),
- d_state (NO_SYNC),
- d_shift_reg(0x0),
- d_dec_b (0x0),
- d_prev_bit_nrzi(0),
- d_received_bytes (0),
- d_sync_received(0),
- d_decoded_bits (0),
- d_lfsr(0x21, 0x0, 16),
- d_frame_buffer (
- new uint8_t[max_frame_len + AX25_MAX_ADDR_LEN
- + AX25_MAX_CTRL_LEN + sizeof(uint16_t)])
+ uint8_t ssid, bool promisc,
+ bool descramble,
+ size_t max_frame_len,
+ size_t n_sync_flags) :
+ gr::sync_block ("ax25_decoder_bm",
+ gr::io_signature::make (1, 1, sizeof(uint8_t)),
+ gr::io_signature::make (0, 0, 0)),
+ d_promisc (promisc),
+ d_descramble (descramble),
+ d_max_frame_len (max_frame_len),
+ d_sync_flags_thr (n_sync_flags - 1),
+ d_state (NO_SYNC),
+ d_shift_reg (0x0),
+ d_dec_b (0x0),
+ d_prev_bit_nrzi (0),
+ d_received_bytes (0),
+ d_sync_received (0),
+ d_decoded_bits (0),
+ d_lfsr (0x21, 0x0, 16),
+ d_frame_buffer (
+ new uint8_t[max_frame_len + AX25_MAX_ADDR_LEN
+ + AX25_MAX_CTRL_LEN + sizeof(uint16_t)])
{
/* Valid PDUs output message port */
message_port_register_out (pmt::mp ("pdu"));
@@ -81,112 +81,113 @@ namespace gr
void
ax25_decoder_bm_impl::descramble_and_decode (const uint8_t* in,
- size_t nitems)
+ size_t nitems)
{
size_t i;
uint8_t descr_bit;
uint8_t dec_bit;
- for(i = 0; i < nitems; i++){
- /* Descramble the input bit */
- descr_bit = d_lfsr.next_bit_descramble(in[i]);
+ for (i = 0; i < nitems; i++) {
+ /* Descramble the input bit */
+ descr_bit = d_lfsr.next_bit_descramble (in[i]);
- /* Perform NRZI decoding */
- dec_bit = (~((descr_bit - d_prev_bit_nrzi) % 2)) & 0x1;
- d_prev_bit_nrzi = descr_bit;
+ /* Perform NRZI decoding */
+ dec_bit = (~((descr_bit - d_prev_bit_nrzi) % 2)) & 0x1;
+ d_prev_bit_nrzi = descr_bit;
- /* In AX.25 the LS bit is sent first */
- d_shift_reg = (d_shift_reg >> 1) | (dec_bit << 7);
- d_dec_b = (d_dec_b >> 1) | (dec_bit << 7);
+ /* In AX.25 the LS bit is sent first */
+ d_shift_reg = (d_shift_reg >> 1) | (dec_bit << 7);
+ d_dec_b = (d_dec_b >> 1) | (dec_bit << 7);
- switch(d_state){
- case NO_SYNC:
- if(d_shift_reg == AX25_SYNC_FLAG){
- enter_sync_state();
- }
- break;
- case IN_SYNC:
- d_decoded_bits++;
- if(d_decoded_bits == 8){
- d_received_bytes++;
- d_decoded_bits = 0;
- if(d_shift_reg == AX25_SYNC_FLAG){
- d_sync_received++;
- if(d_sync_received > d_sync_flags_thr) {
- enter_decoding_state();
- }
- }
- if(d_received_bytes > 3){
- reset_state();
- }
- }
- break;
- case DECODING:
- /*
- * If the received byte was an AX.25 sync flag, there are two
- * possibilities. Either it was the end of frame or just a repeat of the
- * preamble.
- *
- * Also in case in error at the preamble, the G3RUH polynomial should
- * re-sync after 3 repetitions of the SYNC flag. For this reason we demand
- * that the distance between the last SYNC flag is greater than 3 bytes
- */
- if (d_shift_reg == AX25_SYNC_FLAG) {
- if(d_received_bytes < 3) {
- enter_sync_state ();
- }
- else{
- /* Frame end */
- enter_frame_end();
- }
- }
- else if((d_shift_reg & 0xfc) == 0x7c){
- /*This was a stuffed bit */
- d_dec_b <<= 1;
- }
- else if((d_shift_reg & 0xfe) == 0xfe){
- /*This can never happen... Error! */
- if (d_received_bytes > AX25_MIN_ADDR_LEN) {
- message_port_pub (
- pmt::mp ("failed_pdu"),
- pmt::make_blob (d_frame_buffer, d_received_bytes));
- }
- reset_state();
- }
- else{
- d_decoded_bits++;
- if(d_decoded_bits == 8){
- d_frame_buffer[d_received_bytes++] = d_dec_b;
- d_decoded_bits = 0;
+ switch (d_state)
+ {
+ case NO_SYNC:
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ enter_sync_state ();
+ }
+ break;
+ case IN_SYNC:
+ d_decoded_bits++;
+ if (d_decoded_bits == 8) {
+ d_received_bytes++;
+ d_decoded_bits = 0;
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ d_sync_received++;
+ if (d_sync_received > d_sync_flags_thr) {
+ enter_decoding_state ();
+ }
+ }
+ if (d_received_bytes > 3) {
+ reset_state ();
+ }
+ }
+ break;
+ case DECODING:
+ /*
+ * If the received byte was an AX.25 sync flag, there are two
+ * possibilities. Either it was the end of frame or just a repeat of the
+ * preamble.
+ *
+ * Also in case in error at the preamble, the G3RUH polynomial should
+ * re-sync after 3 repetitions of the SYNC flag. For this reason we demand
+ * that the distance between the last SYNC flag is greater than 3 bytes
+ */
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ if (d_received_bytes < 3) {
+ enter_sync_state ();
+ }
+ else {
+ /* Frame end */
+ enter_frame_end ();
+ }
+ }
+ else if ((d_shift_reg & 0xfc) == 0x7c) {
+ /*This was a stuffed bit */
+ d_dec_b <<= 1;
+ }
+ else if ((d_shift_reg & 0xfe) == 0xfe) {
+ /*This can never happen... Error! */
+ if (d_received_bytes > AX25_MIN_ADDR_LEN) {
+ message_port_pub (
+ pmt::mp ("failed_pdu"),
+ pmt::make_blob (d_frame_buffer, d_received_bytes));
+ }
+ reset_state ();
+ }
+ else {
+ d_decoded_bits++;
+ if (d_decoded_bits == 8) {
+ d_frame_buffer[d_received_bytes++] = d_dec_b;
+ d_decoded_bits = 0;
- /*Check if the frame limit was reached */
- if(d_received_bytes >= d_max_frame_len) {
- LOG_WARN("Wrong size");
- message_port_pub (
- pmt::mp ("failed_pdu"),
- pmt::make_blob (d_frame_buffer, d_max_frame_len));
- reset_state();
- }
- }
- }
- break;
- case FRAME_END:
- if (d_shift_reg == AX25_SYNC_FLAG) {
- d_dec_b = 0;
- d_decoded_bits = 0;
- d_received_bytes = 0;
- d_state = FRAME_END;
- }
- else{
- d_decoded_bits++;
- if(d_decoded_bits/8 > 3){
- reset_state();
- }
- }
- break;
- default:
- LOG_ERROR("Invalid decoding state");
- }
+ /*Check if the frame limit was reached */
+ if (d_received_bytes >= d_max_frame_len) {
+ LOG_WARN("Wrong size");
+ message_port_pub (
+ pmt::mp ("failed_pdu"),
+ pmt::make_blob (d_frame_buffer, d_max_frame_len));
+ reset_state ();
+ }
+ }
+ }
+ break;
+ case FRAME_END:
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ d_dec_b = 0;
+ d_decoded_bits = 0;
+ d_received_bytes = 0;
+ d_state = FRAME_END;
+ }
+ else {
+ d_decoded_bits++;
+ if (d_decoded_bits / 8 > 3) {
+ reset_state ();
+ }
+ }
+ break;
+ default:
+ LOG_ERROR("Invalid decoding state");
+ }
}
}
@@ -198,104 +199,104 @@ namespace gr
for (i = 0; i < nitems; i++) {
- /* Perform NRZI decoding */
- dec_bit = (~(((in[i] & 0x1) - d_prev_bit_nrzi) % 2)) & 0x1;
- d_prev_bit_nrzi = in[i] & 0x1;
+ /* Perform NRZI decoding */
+ dec_bit = (~(((in[i] & 0x1) - d_prev_bit_nrzi) % 2)) & 0x1;
+ d_prev_bit_nrzi = in[i] & 0x1;
- /* In AX.25 the LS bit is sent first */
- d_shift_reg = (d_shift_reg >> 1) | (dec_bit << 7);
- d_dec_b = (d_dec_b >> 1) | (dec_bit << 7);
+ /* In AX.25 the LS bit is sent first */
+ d_shift_reg = (d_shift_reg >> 1) | (dec_bit << 7);
+ d_dec_b = (d_dec_b >> 1) | (dec_bit << 7);
- switch (d_state)
- {
- case NO_SYNC:
- if (d_shift_reg == AX25_SYNC_FLAG) {
- enter_sync_state ();
- }
- break;
- case IN_SYNC:
- d_decoded_bits++;
- if (d_decoded_bits == 8) {
- d_received_bytes++;
- d_decoded_bits = 0;
- if (d_shift_reg == AX25_SYNC_FLAG) {
- d_sync_received++;
- if (d_sync_received > d_sync_flags_thr) {
- enter_decoding_state ();
- }
- }
- if (d_received_bytes > 3) {
- reset_state ();
- }
- }
- break;
- case DECODING:
- /*
- * If the received byte was an AX.25 sync flag, there are two
- * possibilities. Either it was the end of frame or just a repeat of the
- * preamble.
- *
- * Also in case in error at the preamble, the G3RUH polynomial should
- * re-sync after 3 repetitions of the SYNC flag. For this reason we demand
- * that the distance between the last SYNC flag is greater than 3 bytes
- */
- if (d_shift_reg == AX25_SYNC_FLAG) {
- if (d_received_bytes < 3) {
- enter_sync_state ();
- }
- else {
- /* Frame end */
- enter_frame_end ();
- }
- }
- else if ((d_shift_reg & 0xfc) == 0x7c) {
- /*This was a stuffed bit */
- d_dec_b <<= 1;
- }
- else if ((d_shift_reg & 0xfe) == 0xfe) {
- /*This can never happen... Error! */
- if (d_received_bytes > AX25_MIN_ADDR_LEN) {
- message_port_pub (
- pmt::mp ("failed_pdu"),
- pmt::make_blob (d_frame_buffer, d_received_bytes));
- }
- reset_state ();
- }
- else {
- d_decoded_bits++;
- if (d_decoded_bits == 8) {
- d_frame_buffer[d_received_bytes++] = d_dec_b;
- d_decoded_bits = 0;
+ switch (d_state)
+ {
+ case NO_SYNC:
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ enter_sync_state ();
+ }
+ break;
+ case IN_SYNC:
+ d_decoded_bits++;
+ if (d_decoded_bits == 8) {
+ d_received_bytes++;
+ d_decoded_bits = 0;
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ d_sync_received++;
+ if (d_sync_received > d_sync_flags_thr) {
+ enter_decoding_state ();
+ }
+ }
+ if (d_received_bytes > 3) {
+ reset_state ();
+ }
+ }
+ break;
+ case DECODING:
+ /*
+ * If the received byte was an AX.25 sync flag, there are two
+ * possibilities. Either it was the end of frame or just a repeat of the
+ * preamble.
+ *
+ * Also in case in error at the preamble, the G3RUH polynomial should
+ * re-sync after 3 repetitions of the SYNC flag. For this reason we demand
+ * that the distance between the last SYNC flag is greater than 3 bytes
+ */
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ if (d_received_bytes < 3) {
+ enter_sync_state ();
+ }
+ else {
+ /* Frame end */
+ enter_frame_end ();
+ }
+ }
+ else if ((d_shift_reg & 0xfc) == 0x7c) {
+ /*This was a stuffed bit */
+ d_dec_b <<= 1;
+ }
+ else if ((d_shift_reg & 0xfe) == 0xfe) {
+ /*This can never happen... Error! */
+ if (d_received_bytes > AX25_MIN_ADDR_LEN) {
+ message_port_pub (
+ pmt::mp ("failed_pdu"),
+ pmt::make_blob (d_frame_buffer, d_received_bytes));
+ }
+ reset_state ();
+ }
+ else {
+ d_decoded_bits++;
+ if (d_decoded_bits == 8) {
+ d_frame_buffer[d_received_bytes++] = d_dec_b;
+ d_decoded_bits = 0;
- /*Check if the frame limit was reached */
- if (d_received_bytes >= d_max_frame_len) {
- LOG_WARN("Wrong size");
- message_port_pub (
- pmt::mp ("failed_pdu"),
- pmt::make_blob (d_frame_buffer, d_max_frame_len));
- reset_state ();
- }
- }
- }
- break;
- case FRAME_END:
- if (d_shift_reg == AX25_SYNC_FLAG) {
- d_dec_b = 0x0;
- d_shift_reg = 0x0;
- d_decoded_bits = 0;
- d_received_bytes = 0;
- d_state = FRAME_END;
- }
- else {
- d_decoded_bits++;
- if (d_decoded_bits / 8 > 3) {
- reset_state();
- }
- }
- break;
- default:
- LOG_ERROR("Invalid decoding state");
- }
+ /*Check if the frame limit was reached */
+ if (d_received_bytes >= d_max_frame_len) {
+ LOG_WARN("Wrong size");
+ message_port_pub (
+ pmt::mp ("failed_pdu"),
+ pmt::make_blob (d_frame_buffer, d_max_frame_len));
+ reset_state ();
+ }
+ }
+ }
+ break;
+ case FRAME_END:
+ if (d_shift_reg == AX25_SYNC_FLAG) {
+ d_dec_b = 0x0;
+ d_shift_reg = 0x0;
+ d_decoded_bits = 0;
+ d_received_bytes = 0;
+ d_state = FRAME_END;
+ }
+ else {
+ d_decoded_bits++;
+ if (d_decoded_bits / 8 > 3) {
+ reset_state ();
+ }
+ }
+ break;
+ default:
+ LOG_ERROR("Invalid decoding state");
+ }
}
}
@@ -348,34 +349,34 @@ namespace gr
/* First check if the size of the frame is valid */
if (d_received_bytes < AX25_MIN_ADDR_LEN + sizeof(uint16_t)) {
- message_port_pub (pmt::mp ("failed_pdu"),
- pmt::make_blob (d_frame_buffer, d_received_bytes));
- d_dec_b = 0x0;
- d_shift_reg = 0x0;
- d_decoded_bits = 0;
- d_received_bytes = 0;
- d_sync_received = 0;
- d_state = FRAME_END;
- return;
+ message_port_pub (pmt::mp ("failed_pdu"),
+ pmt::make_blob (d_frame_buffer, d_received_bytes));
+ d_dec_b = 0x0;
+ d_shift_reg = 0x0;
+ d_decoded_bits = 0;
+ d_received_bytes = 0;
+ d_sync_received = 0;
+ d_state = FRAME_END;
+ return;
}
/* Check if the frame is correct using the FCS field */
fcs = ax25_fcs (d_frame_buffer, d_received_bytes - sizeof(uint16_t));
recv_fcs = (((uint16_t) d_frame_buffer[d_received_bytes - 1]) << 8)
- | d_frame_buffer[d_received_bytes - 2];
+ | d_frame_buffer[d_received_bytes - 2];
if (fcs == recv_fcs) {
- message_port_pub (
- pmt::mp ("pdu"),
- pmt::make_blob (d_frame_buffer,
- d_received_bytes - sizeof(uint16_t)));
+ message_port_pub (
+ pmt::mp ("pdu"),
+ pmt::make_blob (d_frame_buffer,
+ d_received_bytes - sizeof(uint16_t)));
}
else {
- message_port_pub (
- pmt::mp ("failed_pdu"),
- pmt::make_blob (d_frame_buffer,
- d_received_bytes - sizeof(uint16_t)));
- LOG_WARN("Wrong crc");
+ message_port_pub (
+ pmt::mp ("failed_pdu"),
+ pmt::make_blob (d_frame_buffer,
+ d_received_bytes - sizeof(uint16_t)));
+ LOG_WARN("Wrong crc");
}
d_dec_b = 0x0;
d_shift_reg = 0x0;
@@ -388,16 +389,16 @@ namespace gr
int
ax25_decoder_bm_impl::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
{
const uint8_t *in = (const uint8_t *) input_items[0];
- if(d_descramble){
- descramble_and_decode(in, noutput_items);
+ if (d_descramble) {
+ descramble_and_decode (in, noutput_items);
}
- else{
- decode(in, noutput_items);
+ else {
+ decode (in, noutput_items);
}
return noutput_items;
}