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; }