diff --git a/apps/flowgraphs/cw_decoder.grc b/apps/flowgraphs/cw_decoder.grc index 87eec52..b1a9146 100644 --- a/apps/flowgraphs/cw_decoder.grc +++ b/apps/flowgraphs/cw_decoder.grc @@ -116,6 +116,123 @@ 48000 + + variable + + comment + + + + _enabled + 1 + + + _coordinate + (455, 35) + + + _rotation + 0 + + + id + dec + + + value + 8 + + + + variable + + comment + + + + _enabled + 1 + + + _coordinate + (359, 35) + + + _rotation + 0 + + + id + dot_samples + + + value + int((1.2 / wpm) / (1.0 / (audio_samp_rate / 10.0))) + + + + analog_agc2_xx + + attack_rate + 1e-4 + + + alias + + + + comment + + + + affinity + + + + decay_rate + 1e-4 + + + _enabled + 1 + + + _coordinate + (567, 283) + + + _rotation + 0 + + + gain + 1.0 + + + id + analog_agc2_xx_0 + + + max_gain + 65536 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + reference + 1.0 + + + type + complex + + analog_agc2_xx @@ -179,65 +296,6 @@ complex - - analog_agc_xx - - alias - - - - comment - - - - affinity - - - - _enabled - 1 - - - _coordinate - (1372, 339) - - - _rotation - 0 - - - gain - 1.0 - - - id - analog_agc_xx_0 - - - max_gain - 65536 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - rate - 1e-3 - - - reference - 1.0 - - - type - float - - analog_pll_carriertracking_cc @@ -258,7 +316,7 @@ _coordinate - (960, 348) + (919, 299) _rotation @@ -270,11 +328,11 @@ w - 2*math.pi/400.0 + 2*math.pi/100 max_freq - 2*math.pi*2e3/audio_samp_rate + 2*math.pi*2500 maxoutbuf @@ -282,7 +340,7 @@ min_freq - -2*math.pi*2e3/audio_samp_rate + -2*math.pi*2500 minoutbuf @@ -496,7 +554,7 @@ tone. This tone is typically 1 kHz. - blocks_complex_to_mag_squared + blocks_complex_to_mag alias @@ -515,15 +573,15 @@ tone. This tone is typically 1 kHz. _coordinate - (1168, 368) + (1630, 479) _rotation - 0 + 180 id - blocks_complex_to_mag_squared_0 + blocks_complex_to_mag_0 maxoutbuf @@ -581,6 +639,104 @@ tone. This tone is typically 1 kHz. 1 + + blocks_delay + + alias + + + + comment + + + + affinity + + + + delay + int(dot_samples)/dec + + + _enabled + 1 + + + _coordinate + (1302, 403) + + + _rotation + 0 + + + id + blocks_delay_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_ports + 1 + + + type + complex + + + vlen + 1 + + + + blocks_multiply_conjugate_cc + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (1358, 311) + + + _rotation + 0 + + + id + blocks_multiply_conjugate_cc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + vlen + 1 + + blocks_multiply_xx @@ -910,6 +1066,61 @@ tone. This tone is typically 1 kHz. test.txt + + fir_filter_xxx + + alias + + + + comment + + + + affinity + + + + decim + 1 + + + _enabled + True + + + _coordinate + (1574, 315) + + + _rotation + 0 + + + id + fir_filter_xxx_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_delay + 0 + + + taps + [1.0] * (int(dot_samples)/dec) + + + type + ccc + + parameter @@ -1134,7 +1345,7 @@ we shift the LO a little further cutoff_freq - 2e3 + 200 decim @@ -1150,7 +1361,7 @@ we shift the LO a little further _coordinate - (1268, 179) + (1102, 267) _rotation @@ -1178,11 +1389,11 @@ we shift the LO a little further samp_rate - audio_samp_rate + audio_samp_rate/10 width - 1e3 + 0.1e3 win @@ -1201,7 +1412,7 @@ we shift the LO a little further comment - Output samplerate: 20k / 4 = 5k + affinity @@ -1209,11 +1420,11 @@ we shift the LO a little further cutoff_freq - 100 + 2500 decim - 4 + 10 _enabled @@ -1221,19 +1432,19 @@ we shift the LO a little further type - fir_filter_fff + fir_filter_ccf _coordinate - (1584, 420) + (743, 267) _rotation - 180 + 0 gain - 4 + 1 id @@ -1257,7 +1468,82 @@ we shift the LO a little further width - 100 + 0.4e3 + + + win + firdes.WIN_HAMMING + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + 2500 + + + decim + 1 + + + _enabled + True + + + type + fir_filter_ccf + + + _coordinate + (1310, 155) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0_0_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + width + 0.8e3 win @@ -3067,7 +3353,7 @@ we shift the LO a little further satnogs_cw_to_symbol threshold - 0.4 + 2.0 alias @@ -3079,7 +3365,7 @@ we shift the LO a little further conf_level - 0.75 + 0.90 affinity @@ -3091,12 +3377,16 @@ we shift the LO a little further _coordinate - (1336, 460) + (1206, 459) _rotation 180 + + hysteresis + dot_samples/dec + id satnogs_cw_to_symbol_0 @@ -3111,7 +3401,7 @@ we shift the LO a little further sampling_rate - audio_samp_rate/4 + audio_samp_rate/10.0 wpm @@ -3224,7 +3514,7 @@ we shift the LO a little further _coordinate - (952, 444) + (951, 483) _rotation @@ -3639,21 +3929,21 @@ we shift the LO a little further 20 + + analog_agc2_xx_0 + low_pass_filter_0_0 + 0 + 0 + analog_agc2_xx_0_0 blocks_multiply_xx_0 0 1 - - analog_agc_xx_0 - low_pass_filter_0_0 - 0 - 0 - analog_pll_carriertracking_cc_0 - blocks_complex_to_mag_squared_0 + low_pass_filter_0 0 0 @@ -3664,8 +3954,8 @@ we shift the LO a little further 0 - blocks_complex_to_mag_squared_0 - analog_agc_xx_0 + blocks_complex_to_mag_0 + satnogs_cw_to_symbol_0 0 0 @@ -3675,6 +3965,18 @@ we shift the LO a little further 0 0 + + blocks_delay_0 + blocks_multiply_conjugate_cc_0 + 0 + 1 + + + blocks_multiply_conjugate_cc_0 + fir_filter_xxx_0 + 0 + 0 + blocks_multiply_xx_0 blocks_complex_to_real_0 @@ -3688,20 +3990,32 @@ we shift the LO a little further 0 - low_pass_filter_0 - analog_agc2_xx_0_0 + fir_filter_xxx_0 + blocks_complex_to_mag_0 0 0 low_pass_filter_0 - analog_pll_carriertracking_cc_0 + blocks_delay_0 + 0 + 0 + + + low_pass_filter_0 + blocks_multiply_conjugate_cc_0 0 0 low_pass_filter_0_0 - satnogs_cw_to_symbol_0 + analog_pll_carriertracking_cc_0 + 0 + 0 + + + low_pass_filter_0_0_0 + analog_agc2_xx_0_0 0 0 @@ -3713,7 +4027,13 @@ we shift the LO a little further pfb_arb_resampler_xxx_0 - low_pass_filter_0 + analog_agc2_xx_0 + 0 + 0 + + + pfb_arb_resampler_xxx_0 + low_pass_filter_0_0_0 0 0 diff --git a/apps/flowgraphs/fsk_ax25.grc b/apps/flowgraphs/fsk_ax25.grc index e389e60..f19499e 100644 --- a/apps/flowgraphs/fsk_ax25.grc +++ b/apps/flowgraphs/fsk_ax25.grc @@ -136,7 +136,7 @@ _coordinate - (1248, 196) + (1190, 411) _rotation @@ -179,7 +179,7 @@ _coordinate - (992, 316) + (1030, 195) _rotation @@ -406,7 +406,7 @@ _coordinate - (1432, 188) + (1390, 403) _rotation @@ -457,7 +457,7 @@ _coordinate - (1208, 308) + (1206, 187) _rotation @@ -641,7 +641,7 @@ _coordinate - (1616, 164) + (1590, 379) _rotation @@ -677,7 +677,7 @@ omega - 2 + 4 type @@ -998,6 +998,81 @@ we shift the LO a little further 100e3 + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + baudrate / 2 + 1500 + + + decim + 1 + + + _enabled + True + + + type + fir_filter_ccf + + + _coordinate + (1007, 363) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + 4.0 * baudrate + + + width + 1000 + + + win + firdes.WIN_HAMMING + + osmosdr_source @@ -2457,7 +2532,7 @@ we shift the LO a little further atten - 100 + 60 taps @@ -2488,7 +2563,7 @@ we shift the LO a little further _coordinate - (984, 172) + (727, 275) _rotation @@ -2512,7 +2587,7 @@ we shift the LO a little further rrate - (2.0*baudrate)/audio_samp_rate + (4.0*baudrate)/satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx) samp_delay @@ -2520,7 +2595,7 @@ we shift the LO a little further atten - 100 + 60 taps @@ -3088,7 +3163,7 @@ we shift the LO a little further _coordinate - (1384, 300) + (1382, 179) _rotation @@ -3500,6 +3575,12 @@ we shift the LO a little further 0 0 + + low_pass_filter_0 + analog_quadrature_demod_cf_0_0 + 0 + 0 + osmosdr_source_0 blocks_rotator_cc_0 @@ -3512,12 +3593,6 @@ we shift the LO a little further 0 0 - - pfb_arb_resampler_xxx_0 - pfb_arb_resampler_xxx_0_0 - 0 - 0 - pfb_arb_resampler_xxx_0 satnogs_iq_sink_0 @@ -3532,7 +3607,7 @@ we shift the LO a little further pfb_arb_resampler_xxx_0_0 - analog_quadrature_demod_cf_0_0 + low_pass_filter_0 0 0 @@ -3566,6 +3641,12 @@ we shift the LO a little further 0 0 + + satnogs_coarse_doppler_correction_cc_0 + pfb_arb_resampler_xxx_0_0 + 0 + 0 + satnogs_quad_demod_filter_ff_0 digital_binary_slicer_fb_0 diff --git a/apps/flowgraphs/msk_ax25.grc b/apps/flowgraphs/msk_ax25.grc index 321727f..0db7bf8 100644 --- a/apps/flowgraphs/msk_ax25.grc +++ b/apps/flowgraphs/msk_ax25.grc @@ -136,7 +136,7 @@ _coordinate - (1248, 196) + (1214, 419) _rotation @@ -406,7 +406,7 @@ _coordinate - (1432, 188) + (1430, 411) _rotation @@ -641,7 +641,7 @@ _coordinate - (1616, 164) + (1614, 387) _rotation @@ -677,7 +677,7 @@ omega - 2 + 4 type @@ -998,6 +998,81 @@ we shift the LO a little further 100e3 + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + baudrate / 2 + 1500 + + + decim + 1 + + + _enabled + True + + + type + fir_filter_ccf + + + _coordinate + (1022, 371) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + 4.0 * baudrate + + + width + 1000 + + + win + firdes.WIN_HAMMING + + osmosdr_source @@ -2488,7 +2563,7 @@ we shift the LO a little further _coordinate - (984, 172) + (735, 395) _rotation @@ -2496,7 +2571,7 @@ we shift the LO a little further id - pfb_arb_resampler_xxx_0_0 + pfb_arb_resampler_xxx_0_0_0 maxoutbuf @@ -2512,7 +2587,7 @@ we shift the LO a little further rrate - (2.0*baudrate)/audio_samp_rate + (4.0*baudrate)/satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx) samp_delay @@ -2520,7 +2595,7 @@ we shift the LO a little further atten - 100 + 60 taps @@ -3500,6 +3575,12 @@ we shift the LO a little further 0 0 + + low_pass_filter_0 + analog_quadrature_demod_cf_0_0 + 0 + 0 + osmosdr_source_0 blocks_rotator_cc_0 @@ -3512,12 +3593,6 @@ we shift the LO a little further 0 0 - - pfb_arb_resampler_xxx_0 - pfb_arb_resampler_xxx_0_0 - 0 - 0 - pfb_arb_resampler_xxx_0 satnogs_iq_sink_0 @@ -3531,8 +3606,8 @@ we shift the LO a little further 0 - pfb_arb_resampler_xxx_0_0 - analog_quadrature_demod_cf_0_0 + pfb_arb_resampler_xxx_0_0_0 + low_pass_filter_0 0 0 @@ -3566,6 +3641,12 @@ we shift the LO a little further 0 0 + + satnogs_coarse_doppler_correction_cc_0 + pfb_arb_resampler_xxx_0_0_0 + 0 + 0 + satnogs_quad_demod_filter_ff_0 digital_binary_slicer_fb_0 diff --git a/apps/flowgraphs/satnogs_cw_decoder.py b/apps/flowgraphs/satnogs_cw_decoder.py index 630ba3c..4c3af5b 100755 --- a/apps/flowgraphs/satnogs_cw_decoder.py +++ b/apps/flowgraphs/satnogs_cw_decoder.py @@ -5,7 +5,7 @@ # Title: CW Decoder # Author: Manolis Surligas (surligas@gmail.com) # Description: A CW (Morse) Decoder -# Generated: Sun Aug 19 21:56:19 2018 +# Generated: Sun Jan 6 13:47:58 2019 ################################################## from gnuradio import analog @@ -25,7 +25,7 @@ import time class satnogs_cw_decoder(gr.top_block): - def __init__(self, antenna=satnogs.not_set_antenna, bb_gain=satnogs.not_set_rx_bb_gain, bfo_freq=1e3, decoded_data_file_path='/tmp/.satnogs/data/data', dev_args=satnogs.not_set_dev_args, doppler_correction_per_sec=1000, enable_iq_dump=0, file_path='test.txt', if_gain=satnogs.not_set_rx_if_gain, iq_file_path='/tmp/iq.dat', lo_offset=100e3, ppm=0, rf_gain=satnogs.not_set_rx_rf_gain, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', udp_IP='127.0.0.1', udp_port=16887, waterfall_file_path='/tmp/waterfall.dat', wpm=20, samp_rate_rx=satnogs.not_set_samp_rate_rx): + def __init__(self, antenna=satnogs.not_set_antenna, bb_gain=satnogs.not_set_rx_bb_gain, bfo_freq=1e3, decoded_data_file_path='/tmp/.satnogs/data/data', dev_args=satnogs.not_set_dev_args, doppler_correction_per_sec=1000, enable_iq_dump=0, file_path='test.txt', if_gain=satnogs.not_set_rx_if_gain, iq_file_path='/tmp/iq.dat', lo_offset=100e3, ppm=0, rf_gain=satnogs.not_set_rx_rf_gain, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', samp_rate_rx=satnogs.not_set_samp_rate_rx, udp_IP='127.0.0.1', udp_port=16887, waterfall_file_path='/tmp/waterfall.dat', wpm=20): gr.top_block.__init__(self, "CW Decoder") ################################################## @@ -47,16 +47,18 @@ class satnogs_cw_decoder(gr.top_block): self.rigctl_port = rigctl_port self.rx_freq = rx_freq self.rx_sdr_device = rx_sdr_device + self.samp_rate_rx = samp_rate_rx self.udp_IP = udp_IP self.udp_port = udp_port self.waterfall_file_path = waterfall_file_path self.wpm = wpm - self.samp_rate_rx = samp_rate_rx ################################################## # Variables ################################################## self.audio_samp_rate = audio_samp_rate = 48000 + self.dot_samples = dot_samples = int((1.2 / wpm) / (1.0 / (audio_samp_rate / 10.0))) + self.dec = dec = 8 ################################################## # Blocks @@ -68,7 +70,7 @@ class satnogs_cw_decoder(gr.top_block): self.satnogs_morse_decoder_0 = satnogs.morse_decoder(ord('#'), 3) self.satnogs_iq_sink_0 = satnogs.iq_sink(16768, iq_file_path, False, enable_iq_dump) self.satnogs_frame_file_sink_0_0 = satnogs.frame_file_sink(decoded_data_file_path, 0) - self.satnogs_cw_to_symbol_0 = satnogs.cw_to_symbol(audio_samp_rate/4, 0.4, 0.75, wpm) + self.satnogs_cw_to_symbol_0 = satnogs.cw_to_symbol(audio_samp_rate/10.0, 2.0, 0.90, wpm, dot_samples/dec) self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx)) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_ccf( audio_samp_rate/satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), @@ -89,20 +91,26 @@ class satnogs_cw_decoder(gr.top_block): self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(rx_sdr_device, antenna), 0) self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), 0) - self.low_pass_filter_0_0 = filter.fir_filter_fff(4, firdes.low_pass( - 4, audio_samp_rate, 100, 100, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0_0_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, audio_samp_rate, 2500, 0.8e3, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0_0 = filter.fir_filter_ccf(10, firdes.low_pass( + 1, audio_samp_rate, 2500, 0.4e3, firdes.WIN_HAMMING, 6.76)) self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( - 1, audio_samp_rate, 2e3, 1e3, firdes.WIN_HAMMING, 6.76)) + 1, audio_samp_rate/10, 200, 0.1e3, firdes.WIN_HAMMING, 6.76)) + self.fir_filter_xxx_0 = filter.fir_filter_ccc(1, ([1.0] * (int(dot_samples)/dec))) + self.fir_filter_xxx_0.declare_sample_delay(0) self.blocks_rotator_cc_0 = blocks.rotator_cc(-2.0 * math.pi * (lo_offset / satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx))) self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) + self.blocks_multiply_conjugate_cc_0 = blocks.multiply_conjugate_cc(1) + self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, int(dot_samples)/dec) self.blocks_complex_to_real_0 = blocks.complex_to_real(1) - self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1) + self.blocks_complex_to_mag_0 = blocks.complex_to_mag(1) self.analog_sig_source_x_0 = analog.sig_source_c(audio_samp_rate, analog.GR_COS_WAVE, bfo_freq, 1, 0) - self.analog_pll_carriertracking_cc_0 = analog.pll_carriertracking_cc(2*math.pi/400.0, 2*math.pi*2e3/audio_samp_rate, -2*math.pi*2e3/audio_samp_rate) - self.analog_agc_xx_0 = analog.agc_ff(1e-3, 1.0, 1.0) - self.analog_agc_xx_0.set_max_gain(65536) + self.analog_pll_carriertracking_cc_0 = analog.pll_carriertracking_cc(2*math.pi/100, 2*math.pi*2500, -2*math.pi*2500) self.analog_agc2_xx_0_0 = analog.agc2_cc(0.01, 0.001, 0.015, 0.0) self.analog_agc2_xx_0_0.set_max_gain(65536) + self.analog_agc2_xx_0 = analog.agc2_cc(1e-4, 1e-4, 1.0, 1.0) + self.analog_agc2_xx_0.set_max_gain(65536) @@ -113,19 +121,24 @@ class satnogs_cw_decoder(gr.top_block): self.msg_connect((self.satnogs_morse_decoder_0, 'out'), (self.satnogs_frame_file_sink_0_0, 'frame')) self.msg_connect((self.satnogs_morse_decoder_0, 'out'), (self.satnogs_udp_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_agc2_xx_0, 0), (self.low_pass_filter_0_0, 0)) self.connect((self.analog_agc2_xx_0_0, 0), (self.blocks_multiply_xx_0, 1)) - self.connect((self.analog_agc_xx_0, 0), (self.low_pass_filter_0_0, 0)) - self.connect((self.analog_pll_carriertracking_cc_0, 0), (self.blocks_complex_to_mag_squared_0, 0)) + self.connect((self.analog_pll_carriertracking_cc_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 0)) - self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.analog_agc_xx_0, 0)) + self.connect((self.blocks_complex_to_mag_0, 0), (self.satnogs_cw_to_symbol_0, 0)) self.connect((self.blocks_complex_to_real_0, 0), (self.satnogs_ogg_encoder_0, 0)) + self.connect((self.blocks_delay_0, 0), (self.blocks_multiply_conjugate_cc_0, 1)) + self.connect((self.blocks_multiply_conjugate_cc_0, 0), (self.fir_filter_xxx_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.blocks_complex_to_real_0, 0)) self.connect((self.blocks_rotator_cc_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) - self.connect((self.low_pass_filter_0, 0), (self.analog_agc2_xx_0_0, 0)) - self.connect((self.low_pass_filter_0, 0), (self.analog_pll_carriertracking_cc_0, 0)) - self.connect((self.low_pass_filter_0_0, 0), (self.satnogs_cw_to_symbol_0, 0)) + self.connect((self.fir_filter_xxx_0, 0), (self.blocks_complex_to_mag_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.blocks_delay_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.blocks_multiply_conjugate_cc_0, 0)) + self.connect((self.low_pass_filter_0_0, 0), (self.analog_pll_carriertracking_cc_0, 0)) + self.connect((self.low_pass_filter_0_0_0, 0), (self.analog_agc2_xx_0_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.blocks_rotator_cc_0, 0)) - self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.low_pass_filter_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.analog_agc2_xx_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.low_pass_filter_0_0_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.satnogs_iq_sink_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.satnogs_waterfall_sink_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) @@ -244,6 +257,16 @@ class satnogs_cw_decoder(gr.top_block): self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx), 0) self.blocks_rotator_cc_0.set_phase_inc(-2.0 * math.pi * (self.lo_offset / satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx))) + 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.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) + self.osmosdr_source_0.set_sample_rate(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) + self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx), 0) + self.blocks_rotator_cc_0.set_phase_inc(-2.0 * math.pi * (self.lo_offset / satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx))) + def get_udp_IP(self): return self.udp_IP @@ -267,28 +290,35 @@ class satnogs_cw_decoder(gr.top_block): def set_wpm(self, wpm): self.wpm = wpm - - 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.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) - self.osmosdr_source_0.set_sample_rate(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) - self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx), 0) - self.blocks_rotator_cc_0.set_phase_inc(-2.0 * math.pi * (self.lo_offset / satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx))) + self.set_dot_samples(int((1.2 / self.wpm) / (1.0 / (self.audio_samp_rate / 10.0)))) 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.set_dot_samples(int((1.2 / self.wpm) / (1.0 / (self.audio_samp_rate / 10.0)))) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) - self.low_pass_filter_0_0.set_taps(firdes.low_pass(4, self.audio_samp_rate, 100, 100, firdes.WIN_HAMMING, 6.76)) - self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 2e3, 1e3, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0_0_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 2500, 0.8e3, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 2500, 0.4e3, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate/10, 200, 0.1e3, firdes.WIN_HAMMING, 6.76)) self.analog_sig_source_x_0.set_sampling_freq(self.audio_samp_rate) - self.analog_pll_carriertracking_cc_0.set_max_freq(2*math.pi*2e3/self.audio_samp_rate) - self.analog_pll_carriertracking_cc_0.set_min_freq(-2*math.pi*2e3/self.audio_samp_rate) + + def get_dot_samples(self): + return self.dot_samples + + def set_dot_samples(self, dot_samples): + self.dot_samples = dot_samples + self.fir_filter_xxx_0.set_taps(([1.0] * (int(self.dot_samples)/self.dec))) + self.blocks_delay_0.set_dly(int(self.dot_samples)/self.dec) + + def get_dec(self): + return self.dec + + def set_dec(self, dec): + self.dec = dec + self.fir_filter_xxx_0.set_taps(([1.0] * (int(self.dot_samples)/self.dec))) + self.blocks_delay_0.set_dly(int(self.dot_samples)/self.dec) def argument_parser(): @@ -342,6 +372,9 @@ def argument_parser(): parser.add_option( "", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200', help="Set rx_sdr_device [default=%default]") + parser.add_option( + "", "--samp-rate-rx", dest="samp_rate_rx", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_samp_rate_rx), + help="Set samp_rate_rx [default=%default]") parser.add_option( "", "--udp-IP", dest="udp_IP", type="string", default='127.0.0.1', help="Set udp_IP [default=%default]") @@ -354,9 +387,6 @@ def argument_parser(): parser.add_option( "", "--wpm", dest="wpm", type="intx", default=20, help="Set wpm [default=%default]") - parser.add_option( - "", "--samp-rate-rx", dest="samp_rate_rx", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_samp_rate_rx), - help="Set samp_rate_rx [default=%default]") return parser @@ -364,7 +394,7 @@ def main(top_block_cls=satnogs_cw_decoder, options=None): if options is None: options, _ = argument_parser().parse_args() - tb = top_block_cls(antenna=options.antenna, bb_gain=options.bb_gain, bfo_freq=options.bfo_freq, decoded_data_file_path=options.decoded_data_file_path, dev_args=options.dev_args, doppler_correction_per_sec=options.doppler_correction_per_sec, enable_iq_dump=options.enable_iq_dump, file_path=options.file_path, if_gain=options.if_gain, iq_file_path=options.iq_file_path, lo_offset=options.lo_offset, ppm=options.ppm, rf_gain=options.rf_gain, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, udp_IP=options.udp_IP, udp_port=options.udp_port, waterfall_file_path=options.waterfall_file_path, wpm=options.wpm, samp_rate_rx=options.samp_rate_rx) + tb = top_block_cls(antenna=options.antenna, bb_gain=options.bb_gain, bfo_freq=options.bfo_freq, decoded_data_file_path=options.decoded_data_file_path, dev_args=options.dev_args, doppler_correction_per_sec=options.doppler_correction_per_sec, enable_iq_dump=options.enable_iq_dump, file_path=options.file_path, if_gain=options.if_gain, iq_file_path=options.iq_file_path, lo_offset=options.lo_offset, ppm=options.ppm, rf_gain=options.rf_gain, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, samp_rate_rx=options.samp_rate_rx, udp_IP=options.udp_IP, udp_port=options.udp_port, waterfall_file_path=options.waterfall_file_path, wpm=options.wpm) tb.start() tb.wait() diff --git a/apps/flowgraphs/satnogs_fsk_ax25.py b/apps/flowgraphs/satnogs_fsk_ax25.py index 780b1f4..acdef68 100755 --- a/apps/flowgraphs/satnogs_fsk_ax25.py +++ b/apps/flowgraphs/satnogs_fsk_ax25.py @@ -5,7 +5,7 @@ # Title: satnogs_fsk_ax25 # Author: Manolis Surligas (surligas@gmail.com) # Description: Generic FSK AX.25 decoder -# Generated: Fri Aug 17 00:38:04 2018 +# Generated: Sun Jan 6 14:19:34 2019 ################################################## from gnuradio import analog @@ -72,7 +72,7 @@ class satnogs_fsk_ax25(gr.top_block): self.satnogs_ax25_decoder_bm_0_0 = satnogs.ax25_decoder_bm('GND', 0, True, False, 1024) self.satnogs_ax25_decoder_bm_0 = satnogs.ax25_decoder_bm('GND', 0, True, True, 1024) self.pfb_arb_resampler_xxx_0_0 = pfb.arb_resampler_ccf( - (2.0*baudrate)/audio_samp_rate, + (4.0*baudrate)/satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), taps=None, flt_size=32) self.pfb_arb_resampler_xxx_0_0.declare_sample_delay(0) @@ -96,7 +96,9 @@ class satnogs_fsk_ax25(gr.top_block): self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(rx_sdr_device, antenna), 0) self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), 0) - self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(2, 0.25*0.175*0.175, 0.5, 0.175, 0.005) + self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, 4.0 * baudrate, baudrate / 2 + 1500, 1000, firdes.WIN_HAMMING, 6.76)) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(4, 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_0 = filter.dc_blocker_ff(1024, True) self.dc_blocker_xx_0 = filter.dc_blocker_ff(1024, True) @@ -122,13 +124,14 @@ class satnogs_fsk_ax25(gr.top_block): self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_ax25_decoder_bm_0, 0)) self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_ax25_decoder_bm_0_0, 0)) self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.satnogs_quad_demod_filter_ff_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.analog_quadrature_demod_cf_0_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.blocks_rotator_cc_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.analog_quadrature_demod_cf_0_0_0, 0)) - self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.pfb_arb_resampler_xxx_0_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.satnogs_iq_sink_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.satnogs_waterfall_sink_0, 0)) - self.connect((self.pfb_arb_resampler_xxx_0_0, 0), (self.analog_quadrature_demod_cf_0_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) + self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0_0, 0)) self.connect((self.satnogs_quad_demod_filter_ff_0, 0), (self.digital_binary_slicer_fb_0, 0)) def get_antenna(self): @@ -143,7 +146,8 @@ class satnogs_fsk_ax25(gr.top_block): def set_baudrate(self, baudrate): self.baudrate = baudrate - self.pfb_arb_resampler_xxx_0_0.set_rate((2.0*self.baudrate)/self.audio_samp_rate) + self.pfb_arb_resampler_xxx_0_0.set_rate((4.0*self.baudrate)/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, 4.0 * self.baudrate, self.baudrate / 2 + 1500, 1000, firdes.WIN_HAMMING, 6.76)) def get_bb_gain(self): return self.bb_gain @@ -236,6 +240,7 @@ class satnogs_fsk_ax25(gr.top_block): def set_rx_sdr_device(self, rx_sdr_device): self.rx_sdr_device = rx_sdr_device + self.pfb_arb_resampler_xxx_0_0.set_rate((4.0*self.baudrate)/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_sample_rate(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_gain(satnogs.handle_rx_rf_gain(self.rx_sdr_device, self.rf_gain), 0) @@ -250,6 +255,7 @@ class satnogs_fsk_ax25(gr.top_block): def set_samp_rate_rx(self, samp_rate_rx): self.samp_rate_rx = samp_rate_rx + self.pfb_arb_resampler_xxx_0_0.set_rate((4.0*self.baudrate)/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_sample_rate(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx), 0) @@ -278,7 +284,6 @@ class satnogs_fsk_ax25(gr.top_block): def set_audio_samp_rate(self, audio_samp_rate): self.audio_samp_rate = audio_samp_rate - self.pfb_arb_resampler_xxx_0_0.set_rate((2.0*self.baudrate)/self.audio_samp_rate) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) diff --git a/apps/flowgraphs/satnogs_msk_ax25.py b/apps/flowgraphs/satnogs_msk_ax25.py index 09fe10c..7d12bf6 100755 --- a/apps/flowgraphs/satnogs_msk_ax25.py +++ b/apps/flowgraphs/satnogs_msk_ax25.py @@ -5,7 +5,7 @@ # Title: satnogs_msk_ax25 # Author: Manolis Surligas (surligas@gmail.com) # Description: Generic MSK AX.25 decoder -# Generated: Fri Aug 17 00:38:15 2018 +# Generated: Sun Jan 6 14:17:55 2019 ################################################## from gnuradio import analog @@ -71,11 +71,11 @@ class satnogs_msk_ax25(gr.top_block): self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx)) self.satnogs_ax25_decoder_bm_0_0 = satnogs.ax25_decoder_bm('GND', 0, True, False, 1024) self.satnogs_ax25_decoder_bm_0 = satnogs.ax25_decoder_bm('GND', 0, True, True, 1024) - self.pfb_arb_resampler_xxx_0_0 = pfb.arb_resampler_ccf( - (2.0*baudrate)/audio_samp_rate, + self.pfb_arb_resampler_xxx_0_0_0 = pfb.arb_resampler_ccf( + (4.0*baudrate)/satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), taps=None, flt_size=32) - self.pfb_arb_resampler_xxx_0_0.declare_sample_delay(0) + self.pfb_arb_resampler_xxx_0_0_0.declare_sample_delay(0) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_ccf( audio_samp_rate/satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), @@ -96,7 +96,9 @@ class satnogs_msk_ax25(gr.top_block): self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(rx_sdr_device, antenna), 0) self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx), 0) - self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(2, 0.25*0.175*0.175, 0.5, 0.175, 0.005) + self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, 4.0 * baudrate, baudrate / 2 + 1500, 1000, firdes.WIN_HAMMING, 6.76)) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(4, 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_0 = filter.dc_blocker_ff(1024, True) self.dc_blocker_xx_0 = filter.dc_blocker_ff(1024, True) @@ -122,13 +124,14 @@ class satnogs_msk_ax25(gr.top_block): self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_ax25_decoder_bm_0, 0)) self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_ax25_decoder_bm_0_0, 0)) self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.satnogs_quad_demod_filter_ff_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.analog_quadrature_demod_cf_0_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.blocks_rotator_cc_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.analog_quadrature_demod_cf_0_0_0, 0)) - self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.pfb_arb_resampler_xxx_0_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.satnogs_iq_sink_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.satnogs_waterfall_sink_0, 0)) - self.connect((self.pfb_arb_resampler_xxx_0_0, 0), (self.analog_quadrature_demod_cf_0_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0_0_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) + self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0_0_0, 0)) self.connect((self.satnogs_quad_demod_filter_ff_0, 0), (self.digital_binary_slicer_fb_0, 0)) def get_antenna(self): @@ -143,7 +146,8 @@ class satnogs_msk_ax25(gr.top_block): def set_baudrate(self, baudrate): self.baudrate = baudrate - self.pfb_arb_resampler_xxx_0_0.set_rate((2.0*self.baudrate)/self.audio_samp_rate) + self.pfb_arb_resampler_xxx_0_0_0.set_rate((4.0*self.baudrate)/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, 4.0 * self.baudrate, self.baudrate / 2 + 1500, 1000, firdes.WIN_HAMMING, 6.76)) def get_bb_gain(self): return self.bb_gain @@ -236,6 +240,7 @@ class satnogs_msk_ax25(gr.top_block): def set_rx_sdr_device(self, rx_sdr_device): self.rx_sdr_device = rx_sdr_device + self.pfb_arb_resampler_xxx_0_0_0.set_rate((4.0*self.baudrate)/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_sample_rate(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_gain(satnogs.handle_rx_rf_gain(self.rx_sdr_device, self.rf_gain), 0) @@ -250,6 +255,7 @@ class satnogs_msk_ax25(gr.top_block): def set_samp_rate_rx(self, samp_rate_rx): self.samp_rate_rx = samp_rate_rx + self.pfb_arb_resampler_xxx_0_0_0.set_rate((4.0*self.baudrate)/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_sample_rate(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) self.osmosdr_source_0.set_bandwidth(satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx), 0) @@ -278,7 +284,6 @@ class satnogs_msk_ax25(gr.top_block): def set_audio_samp_rate(self, audio_samp_rate): self.audio_samp_rate = audio_samp_rate - self.pfb_arb_resampler_xxx_0_0.set_rate((2.0*self.baudrate)/self.audio_samp_rate) self.pfb_arb_resampler_xxx_0.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) diff --git a/apps/flowgraphs/satnogs_sstv_pd120_demod.py b/apps/flowgraphs/satnogs_sstv_pd120_demod.py index 6315b41..30c17c0 100755 --- a/apps/flowgraphs/satnogs_sstv_pd120_demod.py +++ b/apps/flowgraphs/satnogs_sstv_pd120_demod.py @@ -5,9 +5,10 @@ # Title: SSTV PD120 Demodulation # Author: Sebastian Schumb (sebastian@sebastains-site.de) # Description: A PD120 SSTV demodulator -# Generated: Fri Apr 5 23:30:50 2019 +# GNU Radio version: 3.7.13.5 ################################################## + from gnuradio import analog from gnuradio import eng_notation from gnuradio import filter @@ -91,6 +92,7 @@ class satnogs_sstv_pd120_demod(gr.top_block): 1, 12000, 1500, 1000, firdes.WIN_HAMMING, 6.76)) self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( 1, audio_samp_rate, deviation+max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + self.hilbert_fc_0 = filter.hilbert_fc(65, firdes.WIN_HAMMING, 6.76) self.freq_xlating_fir_filter_xxx_0_0 = filter.freq_xlating_fir_filter_ccc(4, (63, ), 1750, audio_samp_rate) 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.blks2_rational_resampler_xxx_1 = filter.rational_resampler_ccc( @@ -114,14 +116,15 @@ class satnogs_sstv_pd120_demod(gr.top_block): ################################################## self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq')) self.connect((self.analog_nbfm_rx_0, 0), (self.low_pass_filter_0_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0, 0), (self.hilbert_fc_0, 0)) self.connect((self.analog_quadrature_demod_cf_0, 0), (self.satnogs_ogg_encoder_0, 0)) self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.low_pass_filter_0, 0)) self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.satnogs_iq_sink_0, 0)) self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.satnogs_waterfall_sink_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blks2_rational_resampler_xxx_1, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0_0, 0), (self.analog_nbfm_rx_0, 0)) + self.connect((self.hilbert_fc_0, 0), (self.freq_xlating_fir_filter_xxx_0_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.analog_quadrature_demod_cf_0, 0)) - self.connect((self.low_pass_filter_0, 0), (self.freq_xlating_fir_filter_xxx_0_0, 0)) self.connect((self.low_pass_filter_0_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.satnogs_sstv_pd120_sink_0, 0)) diff --git a/apps/flowgraphs/sstv_pd120_demod.grc b/apps/flowgraphs/sstv_pd120_demod.grc index 27e5998..8228e84 100644 --- a/apps/flowgraphs/sstv_pd120_demod.grc +++ b/apps/flowgraphs/sstv_pd120_demod.grc @@ -323,7 +323,7 @@ TX sampling rate _coordinate - (964, 562) + (877, 562) _rotation @@ -374,11 +374,11 @@ TX sampling rate _coordinate - (1204, 474) + (1252, 291) _rotation - 180 + 0 gain @@ -872,7 +872,7 @@ TX sampling rate _coordinate - (1164, 562) + (1076, 562) _rotation @@ -903,6 +903,57 @@ TX sampling rate ccc + + hilbert_fc + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1323, 602) + + + _rotation + 180 + + + id + hilbert_fc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_taps + 65 + + + win + firdes.WIN_HAMMING + + parameter @@ -1159,7 +1210,7 @@ max_modulation_freq = 3000 _coordinate - (781, 538) + (693, 538) _rotation @@ -2680,7 +2731,7 @@ max_modulation_freq = 3000 _coordinate - (590, 562) + (494, 562) _rotation @@ -3017,11 +3068,11 @@ max_modulation_freq = 3000 _coordinate - (1004, 458) + (1531, 275) _rotation - 180 + 0 id @@ -3056,7 +3107,7 @@ max_modulation_freq = 3000 _coordinate - (342, 586) + (263, 586) _rotation @@ -3238,6 +3289,12 @@ max_modulation_freq = 3000 0 0 + + analog_quadrature_demod_cf_0 + hilbert_fc_0 + 0 + 0 + analog_quadrature_demod_cf_0 satnogs_ogg_encoder_0 @@ -3275,14 +3332,14 @@ max_modulation_freq = 3000 0 - low_pass_filter_0 - analog_quadrature_demod_cf_0 + hilbert_fc_0 + freq_xlating_fir_filter_xxx_0_0 0 0 low_pass_filter_0 - freq_xlating_fir_filter_xxx_0_0 + analog_quadrature_demod_cf_0 0 0 diff --git a/grc/satnogs_cw_to_symbol.xml b/grc/satnogs_cw_to_symbol.xml index 984c241..89ea992 100644 --- a/grc/satnogs_cw_to_symbol.xml +++ b/grc/satnogs_cw_to_symbol.xml @@ -1,51 +1,58 @@ - CW to Symbols - satnogs_cw_to_symbol - import satnogs - satnogs.cw_to_symbol($sampling_rate, $threshold, $conf_level, $wpm) - set_act_threshold($threshold) - - - Sampling Rate - sampling_rate - samp_rate - real - + CW to Symbols + satnogs_cw_to_symbol + import satnogs + satnogs.cw_to_symbol($sampling_rate, $threshold, $conf_level, $wpm, $hysteresis) + set_act_threshold($threshold) - - Activation Threshold - threshold - real - - - - Confidence Level - conf_level - 0.9 - real - + + Sampling Rate + sampling_rate + samp_rate + real + - - Words per Minute - wpm - 20 - int - + + Activation Threshold + threshold + real + - - act_threshold - message - 1 - - - - in - float - + + Confidence Level + conf_level + 0.9 + real + - - out - message - + + Words per Minute + wpm + 20 + int + + + + Hysteresis + hysteresis + 0 + int + + + + act_threshold + message + 1 + + + + in + float + + + + out + message + diff --git a/include/satnogs/cw_to_symbol.h b/include/satnogs/cw_to_symbol.h index acf5aef..6a05bbf 100644 --- a/include/satnogs/cw_to_symbol.h +++ b/include/satnogs/cw_to_symbol.h @@ -24,6 +24,9 @@ #include #include +#define MIN_WPM 5 +#define MAX_WPM 50 + namespace gr { namespace satnogs @@ -65,10 +68,19 @@ namespace gr * symbols * * @param wpm Morse code Words per Minute + * + * @param hysteresis this value represents the hysteresis of a possible + * filter used before the CW to Symbol block. For example if there is + * a moving average filter with x taps, the full power of the signal + * will be available after x samples. The total length of samples with + * maximum power will be 2*x less. Because the block searches for plateaus + * with proper durations, this filtering hysteresis should be known. + * If no such a filter is used, the hysteresis value should be set to zero. */ static cw_to_symbol::sptr make (double sampling_rate, float threshold, float conf_level = 0.9, - size_t wpm = 20); + size_t wpm = 20, + size_t hysteresis = 0); virtual void set_act_threshold (float thrld) = 0; diff --git a/include/satnogs/morse.h b/include/satnogs/morse.h index af643b5..b7e96cf 100644 --- a/include/satnogs/morse.h +++ b/include/satnogs/morse.h @@ -2,7 +2,7 @@ /* * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module * - * Copyright (C) 2016,2017 + * Copyright (C) 2016-2018 * Libre Space Foundation * * This program is free software: you can redistribute it and/or modify @@ -22,8 +22,6 @@ #ifndef INCLUDE_SATNOGS_MORSE_H_ #define INCLUDE_SATNOGS_MORSE_H_ -#define MIN_WPM 5 -#define MAX_WPM 30 /** * The different Morse symbols */ @@ -32,7 +30,8 @@ typedef enum { MORSE_DASH, //!< Morse dash (-) symbol MORSE_INTRA_SPACE, //!< Space between dot and dash symbols MORSE_S_SPACE, //!< Morse short space between characters - MORSE_L_SPACE //! #include #if BOOST_VERSION >= 106500 - #include +#include #else - #include +#include #endif #include namespace gr { - namespace satnogs - { +namespace satnogs +{ - cw_to_symbol::sptr - cw_to_symbol::make (double sampling_rate, float threshold, float conf_level, - size_t wpm) - { - return gnuradio::get_initial_sptr ( - new cw_to_symbol_impl (sampling_rate, threshold, conf_level, wpm)); - } +cw_to_symbol::sptr +cw_to_symbol::make (double sampling_rate, float threshold, float conf_level, + size_t wpm, size_t hysteresis) +{ + return gnuradio::get_initial_sptr ( + new cw_to_symbol_impl (sampling_rate, threshold, conf_level, wpm, + hysteresis)); +} - /* - * The private constructor - */ - cw_to_symbol_impl::cw_to_symbol_impl (double sampling_rate, float threshold, - float conf_level, size_t wpm) : - gr::sync_block ("cw_to_symbol", - gr::io_signature::make (1, 1, sizeof(float)), - gr::io_signature::make (0, 0, 0)), - d_sampling_rate (sampling_rate), - d_act_thrshld (threshold), - d_confidence_level (conf_level), - d_dot_samples ((1.2 / wpm) * sampling_rate), - d_window_size(0), - d_window_cnt(0), - d_dot_windows_num(0), - d_dec_state (NO_SYNC), - d_prev_space_symbol (true) - { - if (wpm < MIN_WPM) { - throw std::invalid_argument ( - "Decoder can not handle such low WPM setting"); - } +/* + * The private constructor + */ +cw_to_symbol_impl::cw_to_symbol_impl (double sampling_rate, float threshold, + float conf_level, size_t wpm, + size_t hysteresis) : + gr::sync_block ("cw_to_symbol", + gr::io_signature::make (1, 1, sizeof(float)), + gr::io_signature::make (0, 0, 0)), + d_sampling_rate (sampling_rate), + d_act_thrshld (threshold), + d_confidence_level (conf_level), + d_dot_samples ((1.2 / wpm) * sampling_rate), + d_window_size (0), + d_window_cnt (0), + d_idle_cnt (0), + d_dot_windows_num (0), + d_dec_state (NO_SYNC), + d_prev_space_symbol (true) +{ + if (wpm < MIN_WPM) { + throw std::invalid_argument ("Decoder can not handle such low WPM setting"); + } - if (wpm > MAX_WPM) { - throw std::invalid_argument ( - "Decoder can not handle such high WPM setting"); - } + if (wpm > MAX_WPM) { + throw std::invalid_argument ( + "Decoder can not handle such high WPM setting"); + } - if (conf_level > 1.0 || conf_level < 0.5) { - throw std::invalid_argument ( - "Confidence level should be in the range [0.5, 1.0]"); - } + if (conf_level > 1.0 || conf_level < 0.5) { + throw std::invalid_argument ( + "Confidence level should be in the range [0.5, 1.0]"); + } - message_port_register_in (pmt::mp ("act_threshold")); - message_port_register_out (pmt::mp ("out")); + if(hysteresis > d_dot_samples / 4) { + throw std::invalid_argument ("Too large hysteresis value"); + } - /* Register the message handlers */ - set_msg_handler ( - pmt::mp ("act_threshold"), - boost::bind (&cw_to_symbol_impl::set_act_threshold_msg_handler, this, - _1)); + message_port_register_in (pmt::mp ("act_threshold")); + message_port_register_out (pmt::mp ("out")); - /* - * Try to split the CW pulses in smaller windows for detecting faster - * a false alarm. As we use the window size for setting the history - * it should have a reasonably size. - */ - size_t i = 1; - d_window_size = d_dot_samples / i; - while(d_window_size > 64) { - i++; - d_window_size = d_dot_samples / i; - } + /* Register the message handlers */ + set_msg_handler ( + pmt::mp ("act_threshold"), + boost::bind (&cw_to_symbol_impl::set_act_threshold_msg_handler, this, + _1)); - /* NOTE: The dot duration should be a perfect multiple of the window */ - while(d_dot_samples % d_window_size != 0) { - d_window_size++; - } + /* + * Reconsider the dot oulse duration based on the confidence level + * and hysteresis + */ + d_dot_samples = d_dot_samples - 2 * (hysteresis * conf_level); - LOG_WARN("Dot symbol samples: %lu", d_dot_samples); - LOG_WARN("Window size: %lu", d_window_size); - /* Set the duration of each symbol in multiples of the window size */ - d_dot_windows_num = d_dot_samples / d_window_size; - d_dash_windows_num = 3 * d_dot_windows_num; - d_short_pause_windows_num = d_dash_windows_num; - d_long_pause_windows_num = 7 * d_dot_windows_num; + /* + * Try to split the CW pulses in smaller windows for detecting faster + * a false alarm. As we use the window size for setting the history + * it should have a reasonably size. + */ + size_t i = 1; + d_window_size = d_dot_samples / i; + while (d_window_size > 64) { + i++; + d_window_size = d_dot_samples / i; + } - const int alignment_multiple = volk_get_alignment () - / (d_window_size * sizeof(float)); - set_alignment (std::max (1, alignment_multiple)); + /* NOTE: The dot duration should be a perfect multiple of the window */ + while (d_dot_samples % d_window_size != 0) { + d_window_size++; + } - d_const_val = (float *) volk_malloc(d_window_size * sizeof(float), - volk_get_alignment ()); - d_tmp = (float *) volk_malloc(d_window_size * sizeof(float), - volk_get_alignment ()); - d_out = (int32_t *) volk_malloc (d_window_size * sizeof(int32_t), + LOG_DEBUG("Dot symbol samples: %lu", d_dot_samples); + LOG_DEBUG("Window size: %lu", d_window_size); + + /* Set the duration of each symbol in multiples of the window size */ + d_dot_windows_num = d_dot_samples / d_window_size; + d_dash_windows_num = 3 * d_dot_windows_num; + d_short_pause_windows_num = d_dash_windows_num; + d_long_pause_windows_num = 7 * d_dot_windows_num; + + const int alignment_multiple = volk_get_alignment () + / (d_window_size * sizeof(float)); + set_alignment (std::max (1, alignment_multiple)); + + d_const_val = (float *) volk_malloc (d_window_size * sizeof(float), volk_get_alignment ()); + d_tmp = (float *) volk_malloc (d_window_size * sizeof(float), + volk_get_alignment ()); + d_out = (int32_t *) volk_malloc (d_window_size * sizeof(int32_t), + volk_get_alignment ()); - if(!d_const_val || !d_tmp || !d_out) { - throw std::runtime_error("cw_to_symbol: Could not allocate memory"); - } + if (!d_const_val || !d_tmp || !d_out) { + throw std::runtime_error ("cw_to_symbol: Could not allocate memory"); + } - for(i = 0; i < d_window_size; i++) { - d_const_val[i] = threshold; - } - set_history(d_window_size); - } + for (i = 0; i < d_window_size; i++) { + d_const_val[i] = threshold; + } + set_history (d_window_size); +} - inline void - cw_to_symbol_impl::send_symbol_msg (morse_symbol_t s) - { - if(s == MORSE_S_SPACE || s == MORSE_L_SPACE) { - d_prev_space_symbol = true; - } - else{ - d_prev_space_symbol = false; - } - message_port_pub (pmt::mp ("out"), pmt::from_long (s)); - } +inline void +cw_to_symbol_impl::send_symbol_msg (morse_symbol_t s) +{ + if (s == MORSE_S_SPACE || s == MORSE_L_SPACE) { + d_prev_space_symbol = true; + } + else { + d_prev_space_symbol = false; + } + message_port_pub (pmt::mp ("out"), pmt::from_long (s)); +} - inline bool - cw_to_symbol_impl::check_conf_level(size_t cnt, size_t target) - { - return ((float)cnt > target * d_confidence_level); - } +inline bool +cw_to_symbol_impl::check_conf_level (size_t cnt, size_t target) +{ + return ((float) cnt > target * d_confidence_level); +} - /* - * Our virtual destructor. - */ - cw_to_symbol_impl::~cw_to_symbol_impl () - { - volk_free (d_const_val); - volk_free (d_tmp); - volk_free (d_out); - } +/* + * Our virtual destructor. + */ +cw_to_symbol_impl::~cw_to_symbol_impl () +{ + volk_free (d_const_val); + volk_free (d_tmp); + volk_free (d_out); +} - inline void - cw_to_symbol_impl::set_idle () - { - d_dec_state = NO_SYNC; - d_window_cnt = 0; - } +inline void +cw_to_symbol_impl::set_idle () +{ + d_dec_state = NO_SYNC; + d_window_cnt = 0; + d_idle_cnt = 0; +} - inline void - cw_to_symbol_impl::set_short_on () - { - d_dec_state = SEARCH_DOT; - d_window_cnt = 1; - } +inline void +cw_to_symbol_impl::set_short_on () +{ + d_dec_state = SEARCH_DOT; + d_window_cnt = 1; +} - inline void - cw_to_symbol_impl::set_long_on () - { - d_dec_state = SEARCH_DASH; - } +inline void +cw_to_symbol_impl::set_long_on () +{ + d_dec_state = SEARCH_DASH; +} - inline void - cw_to_symbol_impl::set_search_space () - { - d_dec_state = SEARCH_SPACE; - d_window_cnt = 1; - } +inline void +cw_to_symbol_impl::set_search_space () +{ + d_dec_state = SEARCH_SPACE; + d_window_cnt = 1; +} - void - cw_to_symbol_impl::set_act_threshold_msg_handler (pmt::pmt_t msg) - { - if (pmt::is_pair (msg)) { - set_act_threshold (pmt::to_double (pmt::cdr (msg))); +void +cw_to_symbol_impl::set_act_threshold_msg_handler (pmt::pmt_t msg) +{ + if (pmt::is_pair (msg)) { + set_act_threshold (pmt::to_double (pmt::cdr (msg))); + } +} + +int +cw_to_symbol_impl::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + bool triggered; + size_t i; + const float *in_old = (const float *) input_items[0]; + const float *in = in_old + history () - 1; + + if (noutput_items < 0) { + return noutput_items; + } + + /* During idle state search for a possible trigger */ + if (d_dec_state == NO_SYNC) { + for (i = 0; i < (size_t) noutput_items; i++) { + /* + * Clamp the input so the window mean is not affected by strong spikes + * Good luck understanding this black magic shit! + */ + triggered = is_triggered (in_old + i, d_window_size); + if (triggered) { + LOG_DEBUG("Triggered!"); + set_short_on (); + return i + 1; } } + d_idle_cnt += noutput_items / d_window_size; + if(d_idle_cnt > 10 * d_long_pause_windows_num) { + send_symbol_msg (MORSE_END_MSG_SPACE); + d_idle_cnt = 0; + } + return noutput_items; + } - int - cw_to_symbol_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - bool triggered; - size_t i; - const float *in_old = (const float *) input_items[0]; - const float *in = in_old + history() - 1; - - if(noutput_items < 0) { - return noutput_items; - } - - /* During idle state search for a possible trigger */ - if(d_dec_state == NO_SYNC) { - for(i = 0; i < (size_t)noutput_items; i++) { - /* - * Clamp the input so the window mean is not affected by strong spikes - * Good luck understanding this black magic shit! - */ - triggered = is_triggered(in_old + i, d_window_size); - if(triggered) { - LOG_DEBUG("Triggered!"); - set_short_on(); - return i+1; + /* From now one, we handle the input in multiples of a window */ + for (i = 0; i < (size_t) noutput_items / d_window_size; i++) { + triggered = is_triggered (in + i * d_window_size, d_window_size); + switch (d_dec_state) + { + case SEARCH_DOT: + if (triggered) { + d_window_cnt++; + if (d_window_cnt > d_dot_windows_num) { + set_long_on (); + LOG_DEBUG("Going to search for long sequence"); } } - return noutput_items; - } - - /* From now one, we handle the input in multiples of a window */ - for (i = 0; i < (size_t)noutput_items / d_window_size; i++) { - triggered = is_triggered(in + i * d_window_size, d_window_size); - switch(d_dec_state) { - case SEARCH_DOT: - if(triggered) { - d_window_cnt++; - if(d_window_cnt > d_dot_windows_num) { - set_long_on(); - LOG_DEBUG("Going to search for long sequence"); - } - } - else { - if(check_conf_level(d_window_cnt, d_dot_windows_num)) { - LOG_DEBUG("DOT"); - send_symbol_msg(MORSE_DOT); - } - LOG_DEBUG("Going to search for space: win cnt %lu", d_window_cnt); - set_search_space (); - } - break; - case SEARCH_DASH: - if(triggered) { - d_window_cnt++; - } - else{ - if(check_conf_level(d_window_cnt, d_dash_windows_num)) { - LOG_DEBUG("DASH"); - send_symbol_msg(MORSE_DASH); - } - else{ - LOG_DEBUG("DOT"); - send_symbol_msg(MORSE_DOT); - } - set_search_space (); - LOG_DEBUG("Going to search for space"); - } - break; - case SEARCH_SPACE: - if (triggered) { - if(check_conf_level(d_window_cnt, d_long_pause_windows_num)) { - LOG_DEBUG("LONG SPACE"); - send_symbol_msg(MORSE_L_SPACE); - } - else if(check_conf_level(d_window_cnt, d_short_pause_windows_num)){ - LOG_DEBUG("SHORT SPACE"); - send_symbol_msg(MORSE_S_SPACE); - } - set_short_on(); - LOG_DEBUG("Going to search for dot"); - } - else{ - d_window_cnt++; - if(d_window_cnt > d_long_pause_windows_num) { - LOG_DEBUG("LONG SPACE"); - send_symbol_msg(MORSE_L_SPACE); - set_idle(); - LOG_DEBUG("Going to idle"); - return (i + 1) * d_window_size; - } - } - break; - default: - LOG_ERROR("Invalid decoder state"); + else { + if (check_conf_level (d_window_cnt, d_dot_windows_num)) { + LOG_DEBUG("DOT"); + send_symbol_msg (MORSE_DOT); + } + LOG_DEBUG("Going to search for space: win cnt %lu", d_window_cnt); + set_search_space (); } + break; + case SEARCH_DASH: + if (triggered) { + d_window_cnt++; + } + else { + if (check_conf_level (d_window_cnt, d_dash_windows_num)) { + LOG_DEBUG("DASH"); + send_symbol_msg (MORSE_DASH); + } + else { + LOG_DEBUG("DOT"); + send_symbol_msg (MORSE_DOT); + } + set_search_space (); + LOG_DEBUG("Going to search for space"); + } + break; + case SEARCH_SPACE: + if (triggered) { + if (check_conf_level (d_window_cnt, d_long_pause_windows_num)) { + LOG_DEBUG("LONG SPACE"); + send_symbol_msg (MORSE_L_SPACE); + } + else if (check_conf_level (d_window_cnt, d_short_pause_windows_num)) { + LOG_DEBUG("SHORT SPACE"); + send_symbol_msg (MORSE_S_SPACE); + } + set_short_on (); + LOG_DEBUG("Going to search for dot"); + } + else { + d_window_cnt++; + if (d_window_cnt > d_long_pause_windows_num) { + LOG_DEBUG("LONG SPACE"); + send_symbol_msg (MORSE_L_SPACE); + set_idle (); + LOG_DEBUG("Going to idle"); + return (i + 1) * d_window_size; + } + } + break; + default: + LOG_ERROR("Invalid decoder state"); } - return i * d_window_size; - } + } + return i * d_window_size; +} - /** - * Sets a new activation threshold. - * @param thrhld the new threshold. - */ - void - cw_to_symbol_impl::set_act_threshold (float thrhld) - { - d_act_thrshld = thrhld; - } +/** + * Sets a new activation threshold. + * @param thrhld the new threshold. + */ +void +cw_to_symbol_impl::set_act_threshold (float thrhld) +{ + d_act_thrshld = thrhld; +} - /** - * Clamps the input and performs at the same time binary slicing. - * With this way, a decision based on moving average is not affected - * by strong peaks. - * @param out the output buffer with the binary sliced output - * @param in the input signal - * @param len number of samples to process - */ - inline void - cw_to_symbol_impl::clamp_input (int32_t* out, const float* in, size_t len) - { - volk_32f_x2_subtract_32f(d_tmp, in, d_const_val, len); - volk_32f_binary_slicer_32i(d_out, d_tmp, len); - } +/** + * Clamps the input and performs at the same time binary slicing. + * With this way, a decision based on moving average is not affected + * by strong peaks. + * @param out the output buffer with the binary sliced output + * @param in the input signal + * @param len number of samples to process + */ +inline void +cw_to_symbol_impl::clamp_input (int32_t* out, const float* in, size_t len) +{ + volk_32f_x2_subtract_32f (d_tmp, in, d_const_val, len); + volk_32f_binary_slicer_32i (d_out, d_tmp, len); +} - static inline int32_t - hadd (const int32_t* in, size_t len) - { - size_t i; - int32_t cnt = 0; - for(i = 0; i < len; i++) { - cnt += in[i]; - } - return cnt; - } +static inline int32_t +hadd (const int32_t* in, size_t len) +{ + size_t i; + int32_t cnt = 0; + for (i = 0; i < len; i++) { + cnt += in[i]; + } + return cnt; +} - inline bool - cw_to_symbol_impl::is_triggered (const float* in, size_t len) - { - int32_t cnt; - clamp_input(d_out, in, len); - cnt = hadd(d_out, len); - return (cnt >= (int32_t)(d_window_size * d_confidence_level)) ? true : false; - } +inline bool +cw_to_symbol_impl::is_triggered (const float* in, size_t len) +{ + int32_t cnt; + clamp_input (d_out, in, len); + cnt = hadd (d_out, len); + return (cnt >= (int32_t) (d_window_size * d_confidence_level)) ? true : false; +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/cw_to_symbol_impl.h b/lib/cw_to_symbol_impl.h index 59fa4ed..e2fd13b 100644 --- a/lib/cw_to_symbol_impl.h +++ b/lib/cw_to_symbol_impl.h @@ -45,6 +45,7 @@ namespace gr size_t d_dot_samples; size_t d_window_size; size_t d_window_cnt; + size_t d_idle_cnt; size_t d_dot_windows_num; size_t d_dash_windows_num; size_t d_short_pause_windows_num; @@ -84,7 +85,7 @@ namespace gr public: cw_to_symbol_impl (double sampling_rate, float threshold, - float conf_level, size_t wpm); + float conf_level, size_t wpm, size_t hysteresis); ~cw_to_symbol_impl (); // Where all the action really happens diff --git a/lib/morse_decoder_impl.cc b/lib/morse_decoder_impl.cc index c86fb36..e54ddf8 100644 --- a/lib/morse_decoder_impl.cc +++ b/lib/morse_decoder_impl.cc @@ -28,94 +28,99 @@ #include namespace gr { - namespace satnogs - { +namespace satnogs +{ - morse_decoder::sptr - morse_decoder::make (char unrecognized_char, size_t min_frame_len) +morse_decoder::sptr +morse_decoder::make (char unrecognized_char, size_t min_frame_len) +{ + return gnuradio::get_initial_sptr ( + new morse_decoder_impl (unrecognized_char, min_frame_len)); +} + +void +morse_decoder_impl::symbol_msg_handler (pmt::pmt_t msg) +{ + bool res = false; + morse_symbol_t s; + s = (morse_symbol_t) pmt::to_long (msg); + + switch (s) { - return gnuradio::get_initial_sptr ( - new morse_decoder_impl (unrecognized_char, min_frame_len)); - } - - void - morse_decoder_impl::symbol_msg_handler (pmt::pmt_t msg) - { - bool res = false; - std::string str; - morse_symbol_t s; - s = (morse_symbol_t) pmt::to_long (msg); - - switch (s) - { - case MORSE_DOT: - case MORSE_DASH: - case MORSE_S_SPACE: - res = d_morse_tree.received_symbol (s); - break; - /* - * If a word separator occurs it is a good time to retrieve the decoded - * word - */ - case MORSE_L_SPACE: - /* - * Inject a character separator, for the morse decoder to commit - * the outstanding character - */ - res = d_morse_tree.received_symbol (MORSE_S_SPACE); - /* Just ignore the word separator if no word is yet decoded */ - if (d_morse_tree.get_word_len () == 0) { - res = true; - break; - } - str = d_morse_tree.get_word (); - if (str.length () > d_min_frame_len) { - d_morse_tree.reset (); - message_port_pub (pmt::mp ("out"), - pmt::make_blob (str.c_str (), str.length ())); - } - break; - case MORSE_INTRA_SPACE: - /*Ignore it */ - break; - default: - LOG_ERROR("Unknown Morse symbol"); - return; - } - + case MORSE_DOT: + case MORSE_DASH: + case MORSE_S_SPACE: + res = d_morse_tree.received_symbol (s); + break; /* - * If the decoding return false, it means that either an non decode-able - * character situation occurred or the maximum word limit reached + * If a word separator occurs it is a good time to retrieve the decoded + * word */ - if (!res) { - if (d_morse_tree.get_max_word_len () == d_morse_tree.get_word_len ()) { - str = d_morse_tree.get_word (); - d_morse_tree.reset (); - message_port_pub (pmt::mp ("out"), - pmt::make_blob (str.c_str (), str.length ())); - } + case MORSE_L_SPACE: + /* + * Inject a character separator, for the morse decoder to commit + * the outstanding character + */ + res = d_morse_tree.received_symbol (MORSE_S_SPACE); + /* Just ignore the word separator if no word is yet decoded */ + if (d_morse_tree.get_word_len () == 0) { + res = true; + break; } + d_str = d_str.append(d_morse_tree.get_word ()); + d_str = d_str.append(" "); + d_morse_tree.reset (); + break; + case MORSE_INTRA_SPACE: + /*Ignore it */ + break; + case MORSE_END_MSG_SPACE: + if (d_str.length () > d_min_frame_len) { + d_morse_tree.reset (); + message_port_pub (pmt::mp ("out"), + pmt::make_blob (d_str.c_str (), d_str.length ())); + d_str = ""; + } + break; + default: + LOG_ERROR("Unknown Morse symbol"); + return; } - /* - * The private constructor - */ - morse_decoder_impl::morse_decoder_impl (char unrecognized_char, - size_t min_frame_len) : - gr::block ("morse_decoder", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_morse_tree (unrecognized_char), - d_min_frame_len (min_frame_len) - - { - /* Register the input and output msg handler */ - message_port_register_in (pmt::mp ("in")); - message_port_register_out (pmt::mp ("out")); - set_msg_handler ( - pmt::mp ("in"), - boost::bind (&morse_decoder_impl::symbol_msg_handler, this, _1)); + /* + * If the decoding return false, it means that either an non decode-able + * character situation occurred or the maximum word limit reached + */ + if (!res) { + if (d_morse_tree.get_max_word_len () == d_morse_tree.get_word_len ()) { + d_str = d_morse_tree.get_word (); + d_morse_tree.reset (); + message_port_pub (pmt::mp ("out"), + pmt::make_blob (d_str.c_str (), d_str.length ())); } + } +} - } /* namespace satnogs */ +/* + * The private constructor + */ +morse_decoder_impl::morse_decoder_impl (char unrecognized_char, + size_t min_frame_len) : + gr::block ("morse_decoder", gr::io_signature::make (0, 0, 0), + gr::io_signature::make (0, 0, 0)), + d_morse_tree (unrecognized_char), + d_min_frame_len (min_frame_len), + d_str("") + +{ + /* Register the input and output msg handler */ + message_port_register_in (pmt::mp ("in")); + message_port_register_out (pmt::mp ("out")); + set_msg_handler ( + pmt::mp ("in"), + boost::bind (&morse_decoder_impl::symbol_msg_handler, this, _1)); +} + +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/morse_decoder_impl.h b/lib/morse_decoder_impl.h index 0094e46..0eceedc 100644 --- a/lib/morse_decoder_impl.h +++ b/lib/morse_decoder_impl.h @@ -24,24 +24,27 @@ #include #include -namespace gr { - namespace satnogs { +namespace gr +{ +namespace satnogs +{ - class morse_decoder_impl : public morse_decoder - { - private: - morse_tree d_morse_tree; - size_t d_min_frame_len; +class morse_decoder_impl : public morse_decoder +{ - void - symbol_msg_handler(pmt::pmt_t msg); +public: + morse_decoder_impl (char unrecognized_char, size_t min_frame_len); - public: - morse_decoder_impl(char unrecognized_char, size_t min_frame_len); +private: + morse_tree d_morse_tree; + size_t d_min_frame_len; + std::string d_str; - }; + void + symbol_msg_handler (pmt::pmt_t msg); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_MORSE_DECODER_IMPL_H */