diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e95f764..602f7e8 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,11 +8,11 @@ # Contributors * Corey Shields (cshields@gmail.com) -* LongHairedHacker(sebastian@sebastians-site.de) +* Sebastian Schumb (sebastian@sebastians-site.de) * Nikos Karamolegkos (nkaramolegos@csd.uoc.g) * Mark Jessop (vk5qi@rfhead.net) * Fabian P. Schmidt (kerel-fs@gmx.de) * Thanos Gkiolias (agiolias@csd.uoc.gr) * Patrick Dohmen (dl4pd@darc.de) * Kostis Triantayllakis (ctriant@csd.uoc.gr) -* Alexander Jenke \ No newline at end of file +* Alexander Jenke diff --git a/README.md b/README.md index ff0793a..f06be6d 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ for decoding signals from various scientific and academic sattelites. * libpng * libpng++ * git +* swig **Optional** * gr-osmocom (for using the flowgraphs with real SDR hardware) @@ -23,14 +24,15 @@ for decoding signals from various scientific and academic sattelites. ``` apt install -y build-essential cmake gnuradio g++ \ python-mako python-six libogg-dev \ - libvorbis-dev libpng-dev libpng++-dev + libvorbis-dev libpng-dev libpng++-dev \ + swig cd /tmp git clone https://github.com/gnuradio/volk.git cd volk mkdir build cd build cmake .. -make -j 8 +make -j $(nproc --all) sudo make install ``` @@ -41,7 +43,7 @@ sudo make install 3. `mkdir build` 4. `cd build` 5. `cmake ..` -6. `make` +6. `make -j $(nproc --all)` 7. `sudo make install` If this is the first time you are building the gr-satnogs module run diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index b54538f..332ac66 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -37,5 +37,6 @@ GR_PYTHON_INSTALL( flowgraphs/satnogs_fsk_ax25.py flowgraphs/satnogs_msk_ax25.py flowgraphs/satnogs_bpsk_ax25.py + flowgraphs/satnogs_sstv_pd120_demod.py DESTINATION bin ) diff --git a/apps/flowgraphs/afsk1200_ax25.grc b/apps/flowgraphs/afsk1200_ax25.grc index d846ee4..dd1dcf9 100644 --- a/apps/flowgraphs/afsk1200_ax25.grc +++ b/apps/flowgraphs/afsk1200_ax25.grc @@ -217,7 +217,7 @@ _coordinate - (1364, 578) + (1168, 580) _rotation @@ -225,7 +225,7 @@ gain - ((audio_samp_rate/10) / baud_rate)/(math.pi*1) + ((audio_samp_rate/20) / baud_rate)/(math.pi*1) id @@ -260,7 +260,7 @@ _coordinate - (574, 394) + (936, 396) _rotation @@ -283,6 +283,49 @@ 0 + + analog_quadrature_demod_cf + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (813, 283) + + + _rotation + 0 + + + gain + 1.0 + + + id + analog_quadrature_demod_cf_0_0_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + analog_sig_source_x @@ -311,7 +354,7 @@ _coordinate - (750, 646) + (664, 644) _rotation @@ -393,6 +436,85 @@ satnogs.not_set_antenna + + band_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + decim + 1 + + + _enabled + True + + + type + fir_filter_fff + + + _coordinate + (360, 492) + + + _rotation + 0 + + + gain + 1 + + + high_cutoff_freq + 2400 + + + id + band_pass_filter_0 + + + interp + 1 + + + low_cutoff_freq + 1000 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + width + 400 + + + win + firdes.WIN_HAMMING + + parameter @@ -437,7 +559,7 @@ value - 9600.0 + 1200.0 @@ -487,6 +609,61 @@ satnogs.not_set_rx_bb_gain + + blocks_delay + + alias + + + + comment + + + + affinity + + + + delay + 1024/2 + + + _enabled + True + + + _coordinate + (821, 219) + + + _rotation + 0 + + + id + blocks_delay_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_ports + 1 + + + type + complex + + + vlen + 1 + + blocks_float_to_complex @@ -530,6 +707,65 @@ 1 + + blocks_moving_average_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (981, 267) + + + _rotation + 0 + + + id + blocks_moving_average_xx_0 + + + vlen + 1 + + + length + 1024 + + + max_iter + 4096 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + scale + 1.0/1024.0 + + + type + float + + blocks_multiply_xx @@ -550,7 +786,7 @@ _coordinate - (957, 566) + (872, 568) _rotation @@ -581,6 +817,57 @@ 1 + + blocks_multiply_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1308, 223) + + + _rotation + 0 + + + id + blocks_multiply_xx_0_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + blocks_rotator_cc @@ -624,6 +911,57 @@ -2.0 * math.pi * (lo_offset / satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx)) + + blocks_vco_c + + amplitude + 1.0 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1140, 267) + + + _rotation + 0 + + + id + blocks_vco_c_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + sensitivity + -audio_samp_rate + + dc_blocker_xx @@ -644,7 +982,7 @@ _coordinate - (534, 538) + (544, 540) _rotation @@ -675,6 +1013,57 @@ ff + + dc_blocker_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1344, 572) + + + _rotation + 0 + + + id + dc_blocker_xx_0_0 + + + length + 1024 + + + long_form + True + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + type + ff + + parameter @@ -789,11 +1178,11 @@ _coordinate - (2034, 606) + (1928, 752) _rotation - 0 + 180 id @@ -828,7 +1217,7 @@ _coordinate - (1563, 550) + (1928, 548) _rotation @@ -836,11 +1225,11 @@ gain_mu - 0.175 + 0.5/8.0 gain_omega - 0.25*0.175*0.175 + 2*math.pi/100.0 id @@ -860,11 +1249,11 @@ omega_relative_limit - 0.005 + 0.01 omega - (48e3/10)/baud_rate + (48e3/20)/baud_rate type @@ -1193,7 +1582,7 @@ max_modulation_freq = 3000 _coordinate - (1144, 276) + (1208, 348) _rotation @@ -1225,7 +1614,7 @@ max_modulation_freq = 3000 width - 3000 + 1000 win @@ -1252,11 +1641,11 @@ max_modulation_freq = 3000 cutoff_freq - (mark_frequency - space_frequency)/2.0 + (mark_frequency - space_frequency)/2.0 + 250 decim - 10 + 20 _enabled @@ -1268,7 +1657,7 @@ max_modulation_freq = 3000 _coordinate - (1152, 532) + (992, 532) _rotation @@ -1276,7 +1665,7 @@ max_modulation_freq = 3000 gain - 10 + 1 id @@ -1300,7 +1689,82 @@ max_modulation_freq = 3000 width - 1000 + 500 + + + win + firdes.WIN_HAMMING + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + baudrate /2+ 500 /2 + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_fff + + + _coordinate + (1760, 532) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_2_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + baudrate*2 + + + width + 500 win @@ -2781,7 +3245,7 @@ max_modulation_freq = 3000 _coordinate - (640, 196) + (534, 195) _rotation @@ -3338,7 +3802,7 @@ max_modulation_freq = 3000 _coordinate - (1304, 28) + (773, 27) _rotation @@ -3381,11 +3845,11 @@ max_modulation_freq = 3000 _coordinate - (368, 452) + (303, 379) _rotation - 0 + 180 id @@ -3400,53 +3864,6 @@ max_modulation_freq = 3000 audio_samp_rate - - satnogs_quad_demod_filter_ff - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (1795, 578) - - - _rotation - 0 - - - gain - ((audio_samp_rate/10) / baud_rate)/(math.pi*1) - - - id - satnogs_quad_demod_filter_ff_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - win - 80 - - satnogs_tcp_rigctl_msg_source @@ -3526,7 +3943,7 @@ max_modulation_freq = 3000 _coordinate - (1268, 666) + (1292, 785) _rotation @@ -3581,7 +3998,7 @@ max_modulation_freq = 3000 _coordinate - (872, 4) + (550, 3) _rotation @@ -3794,13 +4211,13 @@ max_modulation_freq = 3000 analog_quadrature_demod_cf_0 - digital_clock_recovery_mm_xx_0 + dc_blocker_xx_0_0 0 0 analog_quadrature_demod_cf_0_0 - dc_blocker_xx_0 + band_pass_filter_0 0 0 @@ -3810,36 +4227,78 @@ max_modulation_freq = 3000 0 0 + + analog_quadrature_demod_cf_0_0_0_0 + blocks_moving_average_xx_0 + 0 + 0 + analog_sig_source_x_0 blocks_multiply_xx_0 0 1 + + band_pass_filter_0 + dc_blocker_xx_0 + 0 + 0 + + + blocks_delay_0 + blocks_multiply_xx_0_0 + 0 + 0 + blocks_float_to_complex_0 blocks_multiply_xx_0 0 0 + + blocks_moving_average_xx_0 + blocks_vco_c_0 + 0 + 0 + blocks_multiply_xx_0 low_pass_filter_1 0 0 + + blocks_multiply_xx_0_0 + low_pass_filter_0 + 0 + 0 + blocks_rotator_cc_0 satnogs_coarse_doppler_correction_cc_0 0 0 + + blocks_vco_c_0 + blocks_multiply_xx_0_0 + 0 + 1 + dc_blocker_xx_0 blocks_float_to_complex_0 0 0 + + dc_blocker_xx_0_0 + low_pass_filter_2_0 + 0 + 0 + digital_binary_slicer_fb_0 satnogs_ax25_decoder_bm_0 @@ -3854,7 +4313,7 @@ max_modulation_freq = 3000 digital_clock_recovery_mm_xx_0 - satnogs_quad_demod_filter_ff_0 + digital_binary_slicer_fb_0 0 0 @@ -3870,6 +4329,12 @@ max_modulation_freq = 3000 0 0 + + low_pass_filter_2_0 + digital_clock_recovery_mm_xx_0 + 0 + 0 + osmosdr_source_0 blocks_rotator_cc_0 @@ -3878,7 +4343,13 @@ max_modulation_freq = 3000 pfb_arb_resampler_xxx_0 - low_pass_filter_0 + analog_quadrature_demod_cf_0_0_0_0 + 0 + 0 + + + pfb_arb_resampler_xxx_0 + blocks_delay_0 0 0 @@ -3924,12 +4395,6 @@ max_modulation_freq = 3000 0 0 - - satnogs_quad_demod_filter_ff_0 - digital_binary_slicer_fb_0 - 0 - 0 - satnogs_tcp_rigctl_msg_source_0 satnogs_coarse_doppler_correction_cc_0 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..e48e177 100644 --- a/apps/flowgraphs/fsk_ax25.grc +++ b/apps/flowgraphs/fsk_ax25.grc @@ -136,7 +136,7 @@ _coordinate - (1248, 196) + (1328, 420) _rotation @@ -179,7 +179,7 @@ _coordinate - (992, 316) + (1316, 83) _rotation @@ -202,6 +202,49 @@ 0 + + analog_quadrature_demod_cf + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (965, 259) + + + _rotation + 0 + + + gain + 1.0 + + + id + analog_quadrature_demod_cf_0_0_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + parameter @@ -343,6 +386,171 @@ satnogs.not_set_rx_bb_gain + + blocks_delay + + alias + + + + comment + + + + affinity + + + + delay + 1024/2 + + + _enabled + True + + + _coordinate + (1260, 171) + + + _rotation + 0 + + + id + blocks_delay_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_ports + 1 + + + type + complex + + + vlen + 1 + + + + blocks_moving_average_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1125, 243) + + + _rotation + 0 + + + id + blocks_moving_average_xx_0 + + + vlen + 1 + + + length + 1024 + + + max_iter + 4096 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + scale + 1.0/1024.0 + + + type + float + + + + blocks_multiply_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1452, 175) + + + _rotation + 0 + + + id + blocks_multiply_xx_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + blocks_rotator_cc @@ -386,6 +594,57 @@ -2.0 * math.pi * (lo_offset / satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx)) + + blocks_vco_c + + amplitude + 1.0 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1276, 243) + + + _rotation + 0 + + + id + blocks_vco_c_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + sensitivity + -audio_samp_rate + + dc_blocker_xx @@ -406,7 +665,7 @@ _coordinate - (1432, 188) + (1824, 412) _rotation @@ -457,7 +716,7 @@ _coordinate - (1208, 308) + (1492, 75) _rotation @@ -641,19 +900,19 @@ _coordinate - (1616, 164) + (1768, 556) _rotation - 0 + 180 gain_mu - 0.175 + 0.5/8.0 gain_omega - 0.25*0.175*0.175 + 2 * math.pi / 100 id @@ -673,7 +932,7 @@ omega_relative_limit - 0.005 + 0.01 omega @@ -998,6 +1257,156 @@ we shift the LO a little further 100e3 + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + Avoid aliasing of the polyphase resampler + + + affinity + + + + cutoff_freq + 0.75 * baudrate + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_ccf + + + _coordinate + (832, 372) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + width + 1000 + + + win + firdes.WIN_HAMMING + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + baudrate * 0.60 + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_fff + + + _coordinate + (1584, 372) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_1 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + 2 * baudrate + + + width + baudrate / 8.0 + + + win + firdes.WIN_HAMMING + + osmosdr_source @@ -2457,7 +2866,7 @@ we shift the LO a little further atten - 100 + 60 taps @@ -2488,7 +2897,7 @@ we shift the LO a little further _coordinate - (984, 172) + (1016, 396) _rotation @@ -2496,7 +2905,7 @@ we shift the LO a little further id - pfb_arb_resampler_xxx_0_0 + pfb_arb_resampler_xxx_0_0_0 maxoutbuf @@ -2520,7 +2929,7 @@ we shift the LO a little further atten - 100 + 60 taps @@ -3045,7 +3454,7 @@ we shift the LO a little further _coordinate - (992, 68) + (965, 27) _rotation @@ -3088,7 +3497,7 @@ we shift the LO a little further _coordinate - (1384, 300) + (1667, 67) _rotation @@ -3107,53 +3516,6 @@ we shift the LO a little further audio_samp_rate - - satnogs_quad_demod_filter_ff - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (1664, 580) - - - _rotation - 180 - - - gain - 1.2 - - - id - satnogs_quad_demod_filter_ff_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - win - 80 - - satnogs_tcp_rigctl_msg_source @@ -3288,7 +3650,7 @@ we shift the LO a little further _coordinate - (760, 44) + (726, 3) _rotation @@ -3454,7 +3816,7 @@ we shift the LO a little further analog_quadrature_demod_cf_0_0 - dc_blocker_xx_0 + low_pass_filter_1 0 0 @@ -3464,12 +3826,42 @@ we shift the LO a little further 0 0 + + analog_quadrature_demod_cf_0_0_0_0 + blocks_moving_average_xx_0 + 0 + 0 + + + blocks_delay_0 + blocks_multiply_xx_0 + 0 + 0 + + + blocks_moving_average_xx_0 + blocks_vco_c_0 + 0 + 0 + + + blocks_multiply_xx_0 + low_pass_filter_0 + 0 + 0 + blocks_rotator_cc_0 satnogs_coarse_doppler_correction_cc_0 0 0 + + blocks_vco_c_0 + blocks_multiply_xx_0 + 0 + 1 + dc_blocker_xx_0 digital_clock_recovery_mm_xx_0 @@ -3496,7 +3888,19 @@ we shift the LO a little further digital_clock_recovery_mm_xx_0 - satnogs_quad_demod_filter_ff_0 + digital_binary_slicer_fb_0 + 0 + 0 + + + low_pass_filter_0 + pfb_arb_resampler_xxx_0_0_0 + 0 + 0 + + + low_pass_filter_1 + dc_blocker_xx_0 0 0 @@ -3514,7 +3918,13 @@ we shift the LO a little further pfb_arb_resampler_xxx_0 - pfb_arb_resampler_xxx_0_0 + analog_quadrature_demod_cf_0_0_0_0 + 0 + 0 + + + pfb_arb_resampler_xxx_0 + blocks_delay_0 0 0 @@ -3531,7 +3941,7 @@ we shift the LO a little further 0 - pfb_arb_resampler_xxx_0_0 + pfb_arb_resampler_xxx_0_0_0 analog_quadrature_demod_cf_0_0 0 0 @@ -3566,12 +3976,6 @@ we shift the LO a little further 0 0 - - satnogs_quad_demod_filter_ff_0 - digital_binary_slicer_fb_0 - 0 - 0 - satnogs_tcp_rigctl_msg_source_0 satnogs_coarse_doppler_correction_cc_0 diff --git a/apps/flowgraphs/msk_ax25.grc b/apps/flowgraphs/msk_ax25.grc index 321727f..c42e5da 100644 --- a/apps/flowgraphs/msk_ax25.grc +++ b/apps/flowgraphs/msk_ax25.grc @@ -136,7 +136,7 @@ _coordinate - (1248, 196) + (1544, 420) _rotation @@ -179,7 +179,7 @@ _coordinate - (992, 316) + (1460, 83) _rotation @@ -202,6 +202,49 @@ 0 + + analog_quadrature_demod_cf + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (981, 291) + + + _rotation + 0 + + + gain + 1.0 + + + id + analog_quadrature_demod_cf_0_0_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + parameter @@ -343,6 +386,171 @@ satnogs.not_set_rx_bb_gain + + blocks_delay + + alias + + + + comment + + + + affinity + + + + delay + 1024/2 + + + _enabled + True + + + _coordinate + (1360, 228) + + + _rotation + 0 + + + id + blocks_delay_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_ports + 1 + + + type + complex + + + vlen + 1 + + + + blocks_moving_average_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1164, 275) + + + _rotation + 0 + + + id + blocks_moving_average_xx_0 + + + vlen + 1 + + + length + 1024 + + + max_iter + 4096 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + scale + 1.0/1024.0 + + + type + float + + + + blocks_multiply_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1531, 239) + + + _rotation + 0 + + + id + blocks_multiply_xx_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + blocks_rotator_cc @@ -386,6 +594,57 @@ -2.0 * math.pi * (lo_offset / satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx)) + + blocks_vco_c + + amplitude + 1.0 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1324, 275) + + + _rotation + 0 + + + id + blocks_vco_c_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + sensitivity + -audio_samp_rate + + dc_blocker_xx @@ -406,7 +665,7 @@ _coordinate - (1432, 188) + (1912, 412) _rotation @@ -457,7 +716,7 @@ _coordinate - (1208, 308) + (1659, 75) _rotation @@ -602,7 +861,7 @@ _coordinate - (1512, 592) + (1520, 592) _rotation @@ -641,19 +900,19 @@ _coordinate - (1616, 164) + (1704, 556) _rotation - 0 + 180 gain_mu - 0.175 + 0.5/8.0 gain_omega - 0.25*0.175*0.175 + 2 * math.pi / 100 id @@ -673,7 +932,7 @@ omega_relative_limit - 0.005 + 0.01 omega @@ -998,6 +1257,156 @@ we shift the LO a little further 100e3 + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + Avoid aliasing of the polyphase resampler + + + affinity + + + + cutoff_freq + 0.75 * baudrate + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_ccf + + + _coordinate + (768, 372) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + width + 1000 + + + win + firdes.WIN_HAMMING + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + baudrate * 0.60 + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_fff + + + _coordinate + (1712, 372) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_1 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + 2 * baudrate + + + width + baudrate / 8.0 + + + win + firdes.WIN_HAMMING + + osmosdr_source @@ -2488,7 +2897,7 @@ we shift the LO a little further _coordinate - (984, 172) + (1288, 396) _rotation @@ -2496,7 +2905,7 @@ we shift the LO a little further id - pfb_arb_resampler_xxx_0_0 + pfb_arb_resampler_xxx_0_0_0 maxoutbuf @@ -2520,7 +2929,7 @@ we shift the LO a little further atten - 100 + 60 taps @@ -3045,7 +3454,7 @@ we shift the LO a little further _coordinate - (976, 60) + (1008, 60) _rotation @@ -3088,7 +3497,7 @@ we shift the LO a little further _coordinate - (1384, 300) + (1835, 67) _rotation @@ -3107,53 +3516,6 @@ we shift the LO a little further audio_samp_rate - - satnogs_quad_demod_filter_ff - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (1664, 580) - - - _rotation - 180 - - - gain - 1.2 - - - id - satnogs_quad_demod_filter_ff_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - win - 80 - - satnogs_tcp_rigctl_msg_source @@ -3454,7 +3816,7 @@ we shift the LO a little further analog_quadrature_demod_cf_0_0 - dc_blocker_xx_0 + low_pass_filter_1 0 0 @@ -3464,12 +3826,42 @@ we shift the LO a little further 0 0 + + analog_quadrature_demod_cf_0_0_0_0 + blocks_moving_average_xx_0 + 0 + 0 + + + blocks_delay_0 + blocks_multiply_xx_0 + 0 + 0 + + + blocks_moving_average_xx_0 + blocks_vco_c_0 + 0 + 0 + + + blocks_multiply_xx_0 + low_pass_filter_0 + 0 + 0 + blocks_rotator_cc_0 satnogs_coarse_doppler_correction_cc_0 0 0 + + blocks_vco_c_0 + blocks_multiply_xx_0 + 0 + 1 + dc_blocker_xx_0 digital_clock_recovery_mm_xx_0 @@ -3496,7 +3888,19 @@ we shift the LO a little further digital_clock_recovery_mm_xx_0 - satnogs_quad_demod_filter_ff_0 + digital_binary_slicer_fb_0 + 0 + 0 + + + low_pass_filter_0 + pfb_arb_resampler_xxx_0_0_0 + 0 + 0 + + + low_pass_filter_1 + dc_blocker_xx_0 0 0 @@ -3514,7 +3918,13 @@ we shift the LO a little further pfb_arb_resampler_xxx_0 - pfb_arb_resampler_xxx_0_0 + analog_quadrature_demod_cf_0_0_0_0 + 0 + 0 + + + pfb_arb_resampler_xxx_0 + blocks_delay_0 0 0 @@ -3531,7 +3941,7 @@ we shift the LO a little further 0 - pfb_arb_resampler_xxx_0_0 + pfb_arb_resampler_xxx_0_0_0 analog_quadrature_demod_cf_0_0 0 0 @@ -3566,12 +3976,6 @@ we shift the LO a little further 0 0 - - satnogs_quad_demod_filter_ff_0 - digital_binary_slicer_fb_0 - 0 - 0 - satnogs_tcp_rigctl_msg_source_0 satnogs_coarse_doppler_correction_cc_0 diff --git a/apps/flowgraphs/satellites/reaktor_hello_world_fsk9600_decoder.grc b/apps/flowgraphs/satellites/reaktor_hello_world_fsk9600_decoder.grc index 678597e..69b6807 100644 --- a/apps/flowgraphs/satellites/reaktor_hello_world_fsk9600_decoder.grc +++ b/apps/flowgraphs/satellites/reaktor_hello_world_fsk9600_decoder.grc @@ -175,7 +175,7 @@ _coordinate - (1248, 196) + (904, 412) _rotation @@ -183,11 +183,11 @@ gain - 1.2 + 0.9 id - analog_quadrature_demod_cf_0_0 + analog_quadrature_demod_cf_0_0_0 maxoutbuf @@ -214,11 +214,11 @@ _enabled - True + 1 _coordinate - (992, 316) + (952, 316) _rotation @@ -226,11 +226,54 @@ gain - 0.9 + 1.0 id - analog_quadrature_demod_cf_0_0_0 + analog_quadrature_demod_cf_0_0_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + analog_quadrature_demod_cf + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (1824, 180) + + + _rotation + 0 + + + gain + 1.2 + + + id + analog_quadrature_demod_cf_0_0_0_1 maxoutbuf @@ -382,6 +425,171 @@ satnogs.not_set_rx_bb_gain + + blocks_delay + + alias + + + + comment + + + + affinity + + + + delay + 1024/2 + + + _enabled + 1 + + + _coordinate + (992, 164) + + + _rotation + 0 + + + id + blocks_delay_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_ports + 1 + + + type + complex + + + vlen + 1 + + + + blocks_moving_average_xx + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (1136, 300) + + + _rotation + 0 + + + id + blocks_moving_average_xx_0 + + + vlen + 1 + + + length + 1024 + + + max_iter + 4096 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + scale + 1.0/1024.0 + + + type + float + + + + blocks_multiply_xx + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (1296, 168) + + + _rotation + 0 + + + id + blocks_multiply_xx_0_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + blocks_rotator_cc @@ -402,7 +610,7 @@ _coordinate - (472, 372) + (368, 372) _rotation @@ -425,6 +633,57 @@ -2.0 * math.pi * (lo_offset / satnogs.handle_samp_rate_rx(rx_sdr_device, samp_rate_rx)) + + blocks_vco_c + + amplitude + 1.0 + + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (1296, 300) + + + _rotation + 0 + + + id + blocks_vco_c_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + sensitivity + -audio_samp_rate + + dc_blocker_xx @@ -445,7 +704,7 @@ _coordinate - (1432, 188) + (1120, 404) _rotation @@ -453,7 +712,7 @@ id - dc_blocker_xx_0 + dc_blocker_xx_0_0 length @@ -492,19 +751,19 @@ _enabled - True + 1 _coordinate - (1208, 308) + (1912, 556) _rotation - 0 + 180 id - dc_blocker_xx_0_0 + dc_blocker_xx_0_0_0 length @@ -680,19 +939,19 @@ _coordinate - (1616, 164) + (1672, 532) _rotation - 0 + 180 gain_mu - 0.175 + 0.5/8.0 gain_omega - 0.25*0.175*0.175 + 2 * math.pi / 100 id @@ -712,7 +971,7 @@ omega_relative_limit - 0.005 + 0.01 omega @@ -1037,6 +1296,156 @@ we shift the LO a little further 100e3 + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + 0.75 * baudrate + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_ccf + + + _coordinate + (1424, 132) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + width + 1000 + + + win + firdes.WIN_HAMMING + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + baudrate * 0.60 + + + decim + 1 + + + _enabled + 1 + + + type + fir_filter_fff + + + _coordinate + (1984, 132) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_1 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + 2 * baudrate + + + width + baudrate / 8.0 + + + win + firdes.WIN_HAMMING + + osmosdr_source @@ -2341,7 +2750,7 @@ we shift the LO a little further _coordinate - (216, 284) + (112, 284) _rotation @@ -2464,7 +2873,7 @@ we shift the LO a little further _coordinate - (728, 172) + (624, 172) _rotation @@ -2523,11 +2932,11 @@ we shift the LO a little further _enabled - True + 1 _coordinate - (984, 172) + (1592, 156) _rotation @@ -2535,7 +2944,7 @@ we shift the LO a little further id - pfb_arb_resampler_xxx_0_0 + pfb_arb_resampler_xxx_0_0_0 maxoutbuf @@ -2872,7 +3281,7 @@ we shift the LO a little further _coordinate - (496, 184) + (392, 184) _rotation @@ -3045,7 +3454,7 @@ we shift the LO a little further _coordinate - (992, 68) + (888, 44) _rotation @@ -3088,7 +3497,7 @@ we shift the LO a little further _coordinate - (1384, 300) + (1296, 396) _rotation @@ -3127,7 +3536,7 @@ we shift the LO a little further _coordinate - (216, 148) + (112, 148) _rotation @@ -3241,7 +3650,7 @@ we shift the LO a little further _coordinate - (760, 44) + (656, 44) _rotation @@ -3406,14 +3815,38 @@ we shift the LO a little further - analog_quadrature_demod_cf_0_0 - dc_blocker_xx_0 + analog_quadrature_demod_cf_0_0_0 + dc_blocker_xx_0_0 0 0 - analog_quadrature_demod_cf_0_0_0 - dc_blocker_xx_0_0 + analog_quadrature_demod_cf_0_0_0_0 + blocks_moving_average_xx_0 + 0 + 0 + + + analog_quadrature_demod_cf_0_0_0_1 + low_pass_filter_1 + 0 + 0 + + + blocks_delay_0 + blocks_multiply_xx_0_0 + 0 + 0 + + + blocks_moving_average_xx_0 + blocks_vco_c_0 + 0 + 0 + + + blocks_multiply_xx_0_0 + low_pass_filter_0 0 0 @@ -3424,10 +3857,10 @@ we shift the LO a little further 0 - dc_blocker_xx_0 - digital_clock_recovery_mm_xx_0 + blocks_vco_c_0 + blocks_multiply_xx_0_0 0 - 0 + 1 dc_blocker_xx_0_0 @@ -3435,6 +3868,12 @@ we shift the LO a little further 0 0 + + dc_blocker_xx_0_0_0 + digital_clock_recovery_mm_xx_0 + 0 + 0 + digital_binary_slicer_fb_0 satnogs_frame_acquisition_0 @@ -3447,6 +3886,18 @@ we shift the LO a little further 0 0 + + low_pass_filter_0 + pfb_arb_resampler_xxx_0_0_0 + 0 + 0 + + + low_pass_filter_1 + dc_blocker_xx_0_0_0 + 0 + 0 + osmosdr_source_0 blocks_rotator_cc_0 @@ -3461,7 +3912,13 @@ we shift the LO a little further pfb_arb_resampler_xxx_0 - pfb_arb_resampler_xxx_0_0 + analog_quadrature_demod_cf_0_0_0_0 + 0 + 0 + + + pfb_arb_resampler_xxx_0 + blocks_delay_0 0 0 @@ -3478,8 +3935,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 + analog_quadrature_demod_cf_0_0_0_1 0 0 diff --git a/apps/flowgraphs/satellites/satnogs_reaktor_hello_world_fsk9600_decoder.py b/apps/flowgraphs/satellites/satnogs_reaktor_hello_world_fsk9600_decoder.py index cc74286..78d6a87 100755 --- a/apps/flowgraphs/satellites/satnogs_reaktor_hello_world_fsk9600_decoder.py +++ b/apps/flowgraphs/satellites/satnogs_reaktor_hello_world_fsk9600_decoder.py @@ -5,9 +5,10 @@ # Title: satnogs_reaktor_hello_world_fsk9600_decoder # Author: Manolis Surligas (surligas@gmail.com) # Description: FSK 9600 Decoder for the Reaktor-Hello-World satellite -# Generated: Mon Dec 3 11:51:46 2018 +# GNU Radio version: 3.7.13.5 ################################################## + from gnuradio import analog from gnuradio import blocks from gnuradio import digital @@ -70,11 +71,11 @@ class satnogs_reaktor_hello_world_fsk9600_decoder(gr.top_block): self.satnogs_frame_file_sink_0_1_0 = satnogs.frame_file_sink(decoded_data_file_path, 0) self.satnogs_frame_acquisition_0 = satnogs.frame_acquisition(1, [0xAA, 0xAA, 0xAA, 0xAA], 4, [0x35, 0x2E, 0x35, 0x2E], 3, 1, 256, 3, variable_whitening_0, 2048) 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_0 = pfb.arb_resampler_ccf( + self.pfb_arb_resampler_xxx_0_0_0 = pfb.arb_resampler_ccf( (2.0*baudrate)/audio_samp_rate, 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), @@ -95,13 +96,22 @@ class satnogs_reaktor_hello_world_fsk9600_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.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_1 = filter.fir_filter_fff(1, firdes.low_pass( + 1, 2 * baudrate, baudrate * 0.60, baudrate / 8.0, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, audio_samp_rate, 0.75 * baudrate, 1000, firdes.WIN_HAMMING, 6.76)) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(2, 2 * math.pi / 100, 0.5, 0.5/8.0, 0.01) self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb() + self.dc_blocker_xx_0_0_0 = filter.dc_blocker_ff(1024, True) self.dc_blocker_xx_0_0 = filter.dc_blocker_ff(1024, True) - self.dc_blocker_xx_0 = filter.dc_blocker_ff(1024, True) + self.blocks_vco_c_0 = blocks.vco_c(audio_samp_rate, -audio_samp_rate, 1.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_0 = blocks.multiply_vcc(1) + self.blocks_moving_average_xx_0 = blocks.moving_average_ff(1024, 1.0/1024.0, 4096) + self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, 1024/2) + self.analog_quadrature_demod_cf_0_0_0_1 = analog.quadrature_demod_cf(1.2) + self.analog_quadrature_demod_cf_0_0_0_0 = analog.quadrature_demod_cf(1.0) self.analog_quadrature_demod_cf_0_0_0 = analog.quadrature_demod_cf(0.9) - self.analog_quadrature_demod_cf_0_0 = analog.quadrature_demod_cf(1.2) @@ -111,19 +121,27 @@ class satnogs_reaktor_hello_world_fsk9600_decoder(gr.top_block): self.msg_connect((self.satnogs_frame_acquisition_0, 'out'), (self.satnogs_frame_file_sink_0_1_0, 'frame')) self.msg_connect((self.satnogs_frame_acquisition_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_quadrature_demod_cf_0_0, 0), (self.dc_blocker_xx_0, 0)) self.connect((self.analog_quadrature_demod_cf_0_0_0, 0), (self.dc_blocker_xx_0_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0_0_0, 0), (self.blocks_moving_average_xx_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0_0_1, 0), (self.low_pass_filter_1, 0)) + self.connect((self.blocks_delay_0, 0), (self.blocks_multiply_xx_0_0, 0)) + self.connect((self.blocks_moving_average_xx_0, 0), (self.blocks_vco_c_0, 0)) + self.connect((self.blocks_multiply_xx_0_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.blocks_rotator_cc_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) - self.connect((self.dc_blocker_xx_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) + self.connect((self.blocks_vco_c_0, 0), (self.blocks_multiply_xx_0_0, 1)) self.connect((self.dc_blocker_xx_0_0, 0), (self.satnogs_ogg_encoder_0, 0)) + self.connect((self.dc_blocker_xx_0_0_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) self.connect((self.digital_binary_slicer_fb_0, 0), (self.satnogs_frame_acquisition_0, 0)) self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.pfb_arb_resampler_xxx_0_0_0, 0)) + self.connect((self.low_pass_filter_1, 0), (self.dc_blocker_xx_0_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.analog_quadrature_demod_cf_0_0_0_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_delay_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.analog_quadrature_demod_cf_0_0_0_1, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) def get_antenna(self): @@ -138,7 +156,9 @@ class satnogs_reaktor_hello_world_fsk9600_decoder(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((2.0*self.baudrate)/self.audio_samp_rate) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, 2 * self.baudrate, self.baudrate * 0.60, self.baudrate / 8.0, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 0.75 * self.baudrate, 1000, firdes.WIN_HAMMING, 6.76)) def get_bb_gain(self): return self.bb_gain @@ -279,8 +299,9 @@ class satnogs_reaktor_hello_world_fsk9600_decoder(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_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)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 0.75 * self.baudrate, 1000, firdes.WIN_HAMMING, 6.76)) def argument_parser(): diff --git a/apps/flowgraphs/satnogs_afsk1200_ax25.py b/apps/flowgraphs/satnogs_afsk1200_ax25.py index dfba673..45a36e8 100755 --- a/apps/flowgraphs/satnogs_afsk1200_ax25.py +++ b/apps/flowgraphs/satnogs_afsk1200_ax25.py @@ -5,9 +5,10 @@ # Title: AFSK1200 AX.25 decoder # Author: Manolis Surligas (surligas@gmail.com), Vardakis Giorgos (vardakis.grg@gmail.com) # Description: AFSK1200 AX.25 decoder -# Generated: Sun Nov 25 23:43:12 2018 +# GNU Radio version: 3.7.13.5 ################################################## + from gnuradio import analog from gnuradio import blocks from gnuradio import digital @@ -26,7 +27,7 @@ import time class satnogs_afsk1200_ax25(gr.top_block): - def __init__(self, antenna=satnogs.not_set_antenna, baudrate=9600.0, bb_gain=satnogs.not_set_rx_bb_gain, 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.wav', if_gain=satnogs.not_set_rx_if_gain, iq_file_path='/tmp/iq.dat', lo_offset=100e3, mark_frequency=2200.0, 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, space_frequency=1200.0, udp_IP='127.0.0.1', udp_port=16887, waterfall_file_path='/tmp/waterfall.dat'): + def __init__(self, antenna=satnogs.not_set_antenna, baudrate=1200.0, bb_gain=satnogs.not_set_rx_bb_gain, 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.wav', if_gain=satnogs.not_set_rx_if_gain, iq_file_path='/tmp/iq.dat', lo_offset=100e3, mark_frequency=2200.0, 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, space_frequency=1200.0, udp_IP='127.0.0.1', udp_port=16887, waterfall_file_path='/tmp/waterfall.dat'): gr.top_block.__init__(self, "AFSK1200 AX.25 decoder ") ################################################## @@ -69,7 +70,6 @@ class satnogs_afsk1200_ax25(gr.top_block): self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 10, 1024, waterfall_file_path, 1) self.satnogs_udp_msg_sink_0_0 = satnogs.udp_msg_sink(udp_IP, udp_port, 1500) self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) - self.satnogs_quad_demod_filter_ff_0 = satnogs.quad_demod_filter_ff(((audio_samp_rate/10) / baud_rate)/(math.pi*1)) self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0) self.satnogs_iq_sink_0 = satnogs.iq_sink(16768, iq_file_path, False, enable_iq_dump) self.satnogs_frame_file_sink_0_1_0 = satnogs.frame_file_sink(decoded_data_file_path, 0) @@ -95,19 +95,29 @@ class satnogs_afsk1200_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.low_pass_filter_1 = filter.fir_filter_ccf(10, firdes.low_pass( - 10, audio_samp_rate, (mark_frequency - space_frequency)/2.0, 1000, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_2_0 = filter.fir_filter_fff(1, firdes.low_pass( + 1, baudrate*2, baudrate /2+ 500 /2, 500, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_1 = filter.fir_filter_ccf(20, firdes.low_pass( + 1, audio_samp_rate, (mark_frequency - space_frequency)/2.0 + 250, 500, 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.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff((48e3/10)/baud_rate, 0.25*0.175*0.175, 0.5, 0.175, 0.005) + 1, audio_samp_rate, deviation+max_modulation_freq, 1000, firdes.WIN_HAMMING, 6.76)) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff((48e3/20)/baud_rate, 2*math.pi/100.0, 0.5, 0.5/8.0, 0.01) 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) + self.blocks_vco_c_0 = blocks.vco_c(audio_samp_rate, -audio_samp_rate, 1.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_0 = blocks.multiply_vcc(1) self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) + self.blocks_moving_average_xx_0 = blocks.moving_average_ff(1024, 1.0/1024.0, 4096) self.blocks_float_to_complex_0 = blocks.float_to_complex(1) + self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, 1024/2) + self.band_pass_filter_0 = filter.fir_filter_fff(1, firdes.band_pass( + 1, audio_samp_rate, 1000, 2400, 400, firdes.WIN_HAMMING, 6.76)) self.analog_sig_source_x_0 = analog.sig_source_c(audio_samp_rate, analog.GR_COS_WAVE, -(1200 + 2200) / 2, 1, 0) + self.analog_quadrature_demod_cf_0_0_0_0 = analog.quadrature_demod_cf(1.0) self.analog_quadrature_demod_cf_0_0 = analog.quadrature_demod_cf((2*math.pi*deviation)/audio_samp_rate) - self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf(((audio_samp_rate/10) / baud_rate)/(math.pi*1)) + self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf(((audio_samp_rate/20) / baud_rate)/(math.pi*1)) @@ -119,25 +129,33 @@ class satnogs_afsk1200_ax25(gr.top_block): self.msg_connect((self.satnogs_ax25_decoder_bm_0_0, 'pdu'), (self.satnogs_frame_file_sink_0_1_0, 'frame')) self.msg_connect((self.satnogs_ax25_decoder_bm_0_0, 'pdu'), (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_quadrature_demod_cf_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) - self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.dc_blocker_xx_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0, 0), (self.dc_blocker_xx_0_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.band_pass_filter_0, 0)) self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.satnogs_ogg_encoder_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0_0_0, 0), (self.blocks_moving_average_xx_0, 0)) self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 1)) + self.connect((self.band_pass_filter_0, 0), (self.dc_blocker_xx_0, 0)) + self.connect((self.blocks_delay_0, 0), (self.blocks_multiply_xx_0_0, 0)) self.connect((self.blocks_float_to_complex_0, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.blocks_moving_average_xx_0, 0), (self.blocks_vco_c_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_1, 0)) + self.connect((self.blocks_multiply_xx_0_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.blocks_rotator_cc_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) + self.connect((self.blocks_vco_c_0, 0), (self.blocks_multiply_xx_0_0, 1)) self.connect((self.dc_blocker_xx_0, 0), (self.blocks_float_to_complex_0, 0)) + self.connect((self.dc_blocker_xx_0_0, 0), (self.low_pass_filter_2_0, 0)) 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.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.analog_quadrature_demod_cf_0_0, 0)) self.connect((self.low_pass_filter_1, 0), (self.analog_quadrature_demod_cf_0, 0)) + self.connect((self.low_pass_filter_2_0, 0), (self.digital_clock_recovery_mm_xx_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_quadrature_demod_cf_0_0_0_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_delay_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)) - self.connect((self.satnogs_quad_demod_filter_ff_0, 0), (self.digital_binary_slicer_fb_0, 0)) def get_antenna(self): return self.antenna @@ -151,6 +169,7 @@ class satnogs_afsk1200_ax25(gr.top_block): def set_baudrate(self, baudrate): self.baudrate = baudrate + self.low_pass_filter_2_0.set_taps(firdes.low_pass(1, self.baudrate*2, self.baudrate /2+ 500 /2, 500, firdes.WIN_HAMMING, 6.76)) def get_bb_gain(self): return self.bb_gain @@ -215,7 +234,7 @@ class satnogs_afsk1200_ax25(gr.top_block): def set_mark_frequency(self, mark_frequency): self.mark_frequency = mark_frequency - self.low_pass_filter_1.set_taps(firdes.low_pass(10, self.audio_samp_rate, (self.mark_frequency - self.space_frequency)/2.0, 1000, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, self.audio_samp_rate, (self.mark_frequency - self.space_frequency)/2.0 + 250, 500, firdes.WIN_HAMMING, 6.76)) def get_ppm(self): return self.ppm @@ -274,7 +293,7 @@ class satnogs_afsk1200_ax25(gr.top_block): def set_space_frequency(self, space_frequency): self.space_frequency = space_frequency - self.low_pass_filter_1.set_taps(firdes.low_pass(10, self.audio_samp_rate, (self.mark_frequency - self.space_frequency)/2.0, 1000, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, self.audio_samp_rate, (self.mark_frequency - self.space_frequency)/2.0 + 250, 500, firdes.WIN_HAMMING, 6.76)) def get_udp_IP(self): return self.udp_IP @@ -299,14 +318,14 @@ class satnogs_afsk1200_ax25(gr.top_block): def set_max_modulation_freq(self, max_modulation_freq): self.max_modulation_freq = max_modulation_freq - self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 1000, firdes.WIN_HAMMING, 6.76)) def get_deviation(self): return self.deviation def set_deviation(self, deviation): self.deviation = deviation - self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 1000, firdes.WIN_HAMMING, 6.76)) self.analog_quadrature_demod_cf_0_0.set_gain((2*math.pi*self.deviation)/self.audio_samp_rate) def get_baud_rate(self): @@ -314,8 +333,8 @@ class satnogs_afsk1200_ax25(gr.top_block): def set_baud_rate(self, baud_rate): self.baud_rate = baud_rate - self.digital_clock_recovery_mm_xx_0.set_omega((48e3/10)/self.baud_rate) - self.analog_quadrature_demod_cf_0.set_gain(((self.audio_samp_rate/10) / self.baud_rate)/(math.pi*1)) + self.digital_clock_recovery_mm_xx_0.set_omega((48e3/20)/self.baud_rate) + self.analog_quadrature_demod_cf_0.set_gain(((self.audio_samp_rate/20) / self.baud_rate)/(math.pi*1)) def get_audio_samp_rate(self): return self.audio_samp_rate @@ -323,11 +342,12 @@ class satnogs_afsk1200_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.set_rate(self.audio_samp_rate/satnogs.handle_samp_rate_rx(self.rx_sdr_device, self.samp_rate_rx)) - self.low_pass_filter_1.set_taps(firdes.low_pass(10, self.audio_samp_rate, (self.mark_frequency - self.space_frequency)/2.0, 1000, firdes.WIN_HAMMING, 6.76)) - self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, self.audio_samp_rate, (self.mark_frequency - self.space_frequency)/2.0 + 250, 500, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 1000, firdes.WIN_HAMMING, 6.76)) + self.band_pass_filter_0.set_taps(firdes.band_pass(1, self.audio_samp_rate, 1000, 2400, 400, firdes.WIN_HAMMING, 6.76)) self.analog_sig_source_x_0.set_sampling_freq(self.audio_samp_rate) self.analog_quadrature_demod_cf_0_0.set_gain((2*math.pi*self.deviation)/self.audio_samp_rate) - self.analog_quadrature_demod_cf_0.set_gain(((self.audio_samp_rate/10) / self.baud_rate)/(math.pi*1)) + self.analog_quadrature_demod_cf_0.set_gain(((self.audio_samp_rate/20) / self.baud_rate)/(math.pi*1)) def argument_parser(): @@ -337,7 +357,7 @@ def argument_parser(): "", "--antenna", dest="antenna", type="string", default=satnogs.not_set_antenna, help="Set antenna [default=%default]") parser.add_option( - "", "--baudrate", dest="baudrate", type="eng_float", default=eng_notation.num_to_str(9600.0), + "", "--baudrate", dest="baudrate", type="eng_float", default=eng_notation.num_to_str(1200.0), help="Set baudrate [default=%default]") parser.add_option( "", "--bb-gain", dest="bb_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_bb_gain), 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..576ee1a 100755 --- a/apps/flowgraphs/satnogs_fsk_ax25.py +++ b/apps/flowgraphs/satnogs_fsk_ax25.py @@ -5,9 +5,10 @@ # Title: satnogs_fsk_ax25 # Author: Manolis Surligas (surligas@gmail.com) # Description: Generic FSK AX.25 decoder -# Generated: Fri Aug 17 00:38:04 2018 +# GNU Radio version: 3.7.13.5 ################################################## + from gnuradio import analog from gnuradio import blocks from gnuradio import digital @@ -64,18 +65,17 @@ class satnogs_fsk_ax25(gr.top_block): self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 10, 1024, waterfall_file_path, 1) self.satnogs_udp_msg_sink_0_0 = satnogs.udp_msg_sink(udp_IP, udp_port, 1500) self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) - self.satnogs_quad_demod_filter_ff_0 = satnogs.quad_demod_filter_ff(1.2) self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0) self.satnogs_iq_sink_0 = satnogs.iq_sink(16768, iq_file_path, False, enable_iq_dump) self.satnogs_frame_file_sink_0_1_0 = satnogs.frame_file_sink(decoded_data_file_path, 0) 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( + self.pfb_arb_resampler_xxx_0_0_0 = pfb.arb_resampler_ccf( (2.0*baudrate)/audio_samp_rate, 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,11 +96,20 @@ 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_1 = filter.fir_filter_fff(1, firdes.low_pass( + 1, 2 * baudrate, baudrate * 0.60, baudrate / 8.0, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, audio_samp_rate, 0.75 * baudrate, 1000, firdes.WIN_HAMMING, 6.76)) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(2, 2 * math.pi / 100, 0.5, 0.5/8.0, 0.01) 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) + self.blocks_vco_c_0 = blocks.vco_c(audio_samp_rate, -audio_samp_rate, 1.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_moving_average_xx_0 = blocks.moving_average_ff(1024, 1.0/1024.0, 4096) + self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, 1024/2) + self.analog_quadrature_demod_cf_0_0_0_0 = analog.quadrature_demod_cf(1.0) self.analog_quadrature_demod_cf_0_0_0 = analog.quadrature_demod_cf(0.9) self.analog_quadrature_demod_cf_0_0 = analog.quadrature_demod_cf(1.2) @@ -114,22 +123,29 @@ class satnogs_fsk_ax25(gr.top_block): self.msg_connect((self.satnogs_ax25_decoder_bm_0_0, 'pdu'), (self.satnogs_frame_file_sink_0_1_0, 'frame')) self.msg_connect((self.satnogs_ax25_decoder_bm_0_0, 'pdu'), (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_quadrature_demod_cf_0_0, 0), (self.dc_blocker_xx_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.low_pass_filter_1, 0)) self.connect((self.analog_quadrature_demod_cf_0_0_0, 0), (self.dc_blocker_xx_0_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0_0_0, 0), (self.blocks_moving_average_xx_0, 0)) + self.connect((self.blocks_delay_0, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.blocks_moving_average_xx_0, 0), (self.blocks_vco_c_0, 0)) + self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.blocks_rotator_cc_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) + self.connect((self.blocks_vco_c_0, 0), (self.blocks_multiply_xx_0, 1)) self.connect((self.dc_blocker_xx_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) self.connect((self.dc_blocker_xx_0_0, 0), (self.satnogs_ogg_encoder_0, 0)) 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.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.pfb_arb_resampler_xxx_0_0_0, 0)) + self.connect((self.low_pass_filter_1, 0), (self.dc_blocker_xx_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.analog_quadrature_demod_cf_0_0_0_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_delay_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.analog_quadrature_demod_cf_0_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) - self.connect((self.satnogs_quad_demod_filter_ff_0, 0), (self.digital_binary_slicer_fb_0, 0)) def get_antenna(self): return self.antenna @@ -143,7 +159,9 @@ 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_0.set_rate((2.0*self.baudrate)/self.audio_samp_rate) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, 2 * self.baudrate, self.baudrate * 0.60, self.baudrate / 8.0, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 0.75 * self.baudrate, 1000, firdes.WIN_HAMMING, 6.76)) def get_bb_gain(self): return self.bb_gain @@ -278,8 +296,9 @@ 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_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)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 0.75 * self.baudrate, 1000, firdes.WIN_HAMMING, 6.76)) def argument_parser(): diff --git a/apps/flowgraphs/satnogs_msk_ax25.py b/apps/flowgraphs/satnogs_msk_ax25.py index 09fe10c..7e1f4f7 100755 --- a/apps/flowgraphs/satnogs_msk_ax25.py +++ b/apps/flowgraphs/satnogs_msk_ax25.py @@ -5,9 +5,10 @@ # Title: satnogs_msk_ax25 # Author: Manolis Surligas (surligas@gmail.com) # Description: Generic MSK AX.25 decoder -# Generated: Fri Aug 17 00:38:15 2018 +# GNU Radio version: 3.7.13.5 ################################################## + from gnuradio import analog from gnuradio import blocks from gnuradio import digital @@ -64,18 +65,17 @@ class satnogs_msk_ax25(gr.top_block): self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 10, 1024, waterfall_file_path, 1) self.satnogs_udp_msg_sink_0_0 = satnogs.udp_msg_sink(udp_IP, udp_port, 1500) self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500) - self.satnogs_quad_demod_filter_ff_0 = satnogs.quad_demod_filter_ff(1.2) self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0) self.satnogs_iq_sink_0 = satnogs.iq_sink(16768, iq_file_path, False, enable_iq_dump) self.satnogs_frame_file_sink_0_1_0 = satnogs.frame_file_sink(decoded_data_file_path, 0) 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( + self.pfb_arb_resampler_xxx_0_0_0 = pfb.arb_resampler_ccf( (2.0*baudrate)/audio_samp_rate, 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,11 +96,20 @@ 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_1 = filter.fir_filter_fff(1, firdes.low_pass( + 1, 2 * baudrate, baudrate * 0.60, baudrate / 8.0, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, audio_samp_rate, 0.75 * baudrate, 1000, firdes.WIN_HAMMING, 6.76)) + self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(2, 2 * math.pi / 100, 0.5, 0.5/8.0, 0.01) 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) + self.blocks_vco_c_0 = blocks.vco_c(audio_samp_rate, -audio_samp_rate, 1.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_moving_average_xx_0 = blocks.moving_average_ff(1024, 1.0/1024.0, 4096) + self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, 1024/2) + self.analog_quadrature_demod_cf_0_0_0_0 = analog.quadrature_demod_cf(1.0) self.analog_quadrature_demod_cf_0_0_0 = analog.quadrature_demod_cf(0.9) self.analog_quadrature_demod_cf_0_0 = analog.quadrature_demod_cf(1.2) @@ -114,22 +123,29 @@ class satnogs_msk_ax25(gr.top_block): self.msg_connect((self.satnogs_ax25_decoder_bm_0_0, 'pdu'), (self.satnogs_frame_file_sink_0_1_0, 'frame')) self.msg_connect((self.satnogs_ax25_decoder_bm_0_0, 'pdu'), (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_quadrature_demod_cf_0_0, 0), (self.dc_blocker_xx_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0, 0), (self.low_pass_filter_1, 0)) self.connect((self.analog_quadrature_demod_cf_0_0_0, 0), (self.dc_blocker_xx_0_0, 0)) + self.connect((self.analog_quadrature_demod_cf_0_0_0_0, 0), (self.blocks_moving_average_xx_0, 0)) + self.connect((self.blocks_delay_0, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.blocks_moving_average_xx_0, 0), (self.blocks_vco_c_0, 0)) + self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.blocks_rotator_cc_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0)) + self.connect((self.blocks_vco_c_0, 0), (self.blocks_multiply_xx_0, 1)) self.connect((self.dc_blocker_xx_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) self.connect((self.dc_blocker_xx_0_0, 0), (self.satnogs_ogg_encoder_0, 0)) 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.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.pfb_arb_resampler_xxx_0_0_0, 0)) + self.connect((self.low_pass_filter_1, 0), (self.dc_blocker_xx_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.analog_quadrature_demod_cf_0_0_0_0, 0)) + self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.blocks_delay_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.analog_quadrature_demod_cf_0_0, 0)) self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.pfb_arb_resampler_xxx_0, 0)) - self.connect((self.satnogs_quad_demod_filter_ff_0, 0), (self.digital_binary_slicer_fb_0, 0)) def get_antenna(self): return self.antenna @@ -143,7 +159,9 @@ 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((2.0*self.baudrate)/self.audio_samp_rate) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, 2 * self.baudrate, self.baudrate * 0.60, self.baudrate / 8.0, firdes.WIN_HAMMING, 6.76)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 0.75 * self.baudrate, 1000, firdes.WIN_HAMMING, 6.76)) def get_bb_gain(self): return self.bb_gain @@ -278,8 +296,9 @@ 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_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)) + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, 0.75 * self.baudrate, 1000, firdes.WIN_HAMMING, 6.76)) def argument_parser(): diff --git a/apps/flowgraphs/satnogs_sstv_pd120_demod.py b/apps/flowgraphs/satnogs_sstv_pd120_demod.py new file mode 100755 index 0000000..30c17c0 --- /dev/null +++ b/apps/flowgraphs/satnogs_sstv_pd120_demod.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: SSTV PD120 Demodulation +# Author: Sebastian Schumb (sebastian@sebastains-site.de) +# Description: A PD120 SSTV demodulator +# GNU Radio version: 3.7.13.5 +################################################## + + +from gnuradio import analog +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_sstv_pd120_demod(gr.top_block): + + def __init__(self, antenna=satnogs.not_set_antenna, bb_gain=satnogs.not_set_rx_bb_gain, decoded_data_file_path='/tmp/.satnogs/data/data', dev_args=satnogs.not_set_dev_args, doppler_correction_per_sec=20, enable_iq_dump=0, file_path='test.ogg', 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', waterfall_file_path='/tmp/waterfall.dat'): + gr.top_block.__init__(self, "SSTV PD120 Demodulation") + + ################################################## + # Parameters + ################################################## + self.antenna = antenna + self.bb_gain = bb_gain + self.decoded_data_file_path = decoded_data_file_path + self.dev_args = dev_args + self.doppler_correction_per_sec = doppler_correction_per_sec + self.enable_iq_dump = enable_iq_dump + self.file_path = file_path + self.if_gain = if_gain + self.iq_file_path = iq_file_path + self.lo_offset = lo_offset + self.ppm = ppm + self.rf_gain = rf_gain + 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.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.max_modulation_freq = max_modulation_freq = 3000 + self.filter_rate = filter_rate = 250000 + self.deviation = deviation = 5000 + self.audio_samp_rate = audio_samp_rate = 48000 + + ################################################## + # Blocks + ################################################## + self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink(audio_samp_rate, 0.0, 10, 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/doppler_correction_per_sec, 1500) + self.satnogs_sstv_pd120_sink_0 = satnogs.sstv_pd120_sink(decoded_data_file_path) + self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0) + self.satnogs_iq_sink_0 = satnogs.iq_sink(32767, iq_file_path, False, enable_iq_dump) + self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx) + self.rational_resampler_xxx_0 = filter.rational_resampler_fff( + interpolation=5263, + decimation=12000, + taps=None, + fractional_bw=None, + ) + self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.handle_rx_dev_args(rx_sdr_device, dev_args) ) + 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.handle_rx_rf_gain(rx_sdr_device, rf_gain), 0) + self.osmosdr_source_0.set_if_gain(satnogs.handle_rx_if_gain(rx_sdr_device, if_gain), 0) + self.osmosdr_source_0.set_bb_gain(satnogs.handle_rx_bb_gain(rx_sdr_device, bb_gain), 0) + self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(rx_sdr_device, antenna), 0) + self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0) + + self.low_pass_filter_0_0 = filter.fir_filter_fff(1, firdes.low_pass( + 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( + interpolation=24, + decimation=125, + taps=None, + fractional_bw=None, + ) + self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf((2*math.pi*deviation)/audio_samp_rate) + self.analog_nbfm_rx_0 = analog.nbfm_rx( + audio_rate=12000, + quad_rate=12000, + tau=75e-6, + max_dev=600, + ) + + + + ################################################## + # Connections + ################################################## + 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, 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)) + self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) + + def get_antenna(self): + return self.antenna + + def set_antenna(self, antenna): + self.antenna = antenna + self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(self.rx_sdr_device, self.antenna), 0) + + def get_bb_gain(self): + return self.bb_gain + + def set_bb_gain(self, bb_gain): + self.bb_gain = bb_gain + self.osmosdr_source_0.set_bb_gain(satnogs.handle_rx_bb_gain(self.rx_sdr_device, self.bb_gain), 0) + + def get_decoded_data_file_path(self): + return self.decoded_data_file_path + + def set_decoded_data_file_path(self, decoded_data_file_path): + self.decoded_data_file_path = decoded_data_file_path + + def get_dev_args(self): + return self.dev_args + + def set_dev_args(self, dev_args): + self.dev_args = dev_args + + 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_enable_iq_dump(self): + return self.enable_iq_dump + + def set_enable_iq_dump(self, enable_iq_dump): + self.enable_iq_dump = enable_iq_dump + + def get_file_path(self): + return self.file_path + + def set_file_path(self, file_path): + self.file_path = file_path + + def get_if_gain(self): + return self.if_gain + + def set_if_gain(self, if_gain): + self.if_gain = if_gain + self.osmosdr_source_0.set_if_gain(satnogs.handle_rx_if_gain(self.rx_sdr_device, self.if_gain), 0) + + def get_iq_file_path(self): + return self.iq_file_path + + def set_iq_file_path(self, iq_file_path): + self.iq_file_path = iq_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_rf_gain(self): + return self.rf_gain + + def set_rf_gain(self, rf_gain): + self.rf_gain = rf_gain + self.osmosdr_source_0.set_gain(satnogs.handle_rx_rf_gain(self.rx_sdr_device, self.rf_gain), 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.handle_rx_rf_gain(self.rx_sdr_device, self.rf_gain), 0) + self.osmosdr_source_0.set_if_gain(satnogs.handle_rx_if_gain(self.rx_sdr_device, self.if_gain), 0) + self.osmosdr_source_0.set_bb_gain(satnogs.handle_rx_bb_gain(self.rx_sdr_device, self.bb_gain), 0) + self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(self.rx_sdr_device, self.antenna), 0) + + 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_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_max_modulation_freq(self): + return self.max_modulation_freq + + def set_max_modulation_freq(self, max_modulation_freq): + self.max_modulation_freq = max_modulation_freq + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + + def get_filter_rate(self): + return self.filter_rate + + def set_filter_rate(self, filter_rate): + self.filter_rate = filter_rate + + def get_deviation(self): + return self.deviation + + def set_deviation(self, deviation): + self.deviation = deviation + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_samp_rate, self.deviation+self.max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + self.analog_quadrature_demod_cf_0.set_gain((2*math.pi*self.deviation)/self.audio_samp_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, self.deviation+self.max_modulation_freq, 3000, firdes.WIN_HAMMING, 6.76)) + self.analog_quadrature_demod_cf_0.set_gain((2*math.pi*self.deviation)/self.audio_samp_rate) + + +def argument_parser(): + description = 'A PD120 SSTV demodulator' + parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description) + parser.add_option( + "", "--antenna", dest="antenna", type="string", default=satnogs.not_set_antenna, + help="Set antenna [default=%default]") + parser.add_option( + "", "--bb-gain", dest="bb_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_bb_gain), + help="Set bb_gain [default=%default]") + parser.add_option( + "", "--decoded-data-file-path", dest="decoded_data_file_path", type="string", default='/tmp/.satnogs/data/data', + help="Set decoded_data_file_path [default=%default]") + parser.add_option( + "", "--dev-args", dest="dev_args", type="string", default=satnogs.not_set_dev_args, + help="Set dev_args [default=%default]") + parser.add_option( + "", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=20, + help="Set doppler_correction_per_sec [default=%default]") + parser.add_option( + "", "--enable-iq-dump", dest="enable_iq_dump", type="intx", default=0, + help="Set enable_iq_dump [default=%default]") + parser.add_option( + "", "--file-path", dest="file_path", type="string", default='test.ogg', + help="Set file_path [default=%default]") + parser.add_option( + "", "--if-gain", dest="if_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_if_gain), + help="Set if_gain [default=%default]") + parser.add_option( + "", "--iq-file-path", dest="iq_file_path", type="string", default='/tmp/iq.dat', + help="Set iq_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( + "", "--rf-gain", dest="rf_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_rf_gain), + help="Set rf_gain [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_sstv_pd120_demod, options=None): + if options is None: + options, _ = argument_parser().parse_args() + + tb = top_block_cls(antenna=options.antenna, bb_gain=options.bb_gain, 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, waterfall_file_path=options.waterfall_file_path) + tb.start() + tb.wait() + + +if __name__ == '__main__': + main() diff --git a/apps/flowgraphs/sstv_pd120_demod.grc b/apps/flowgraphs/sstv_pd120_demod.grc new file mode 100644 index 0000000..8228e84 --- /dev/null +++ b/apps/flowgraphs/sstv_pd120_demod.grc @@ -0,0 +1,3376 @@ + + + + Thu May 5 00:22:45 2016 + + options + + author + Sebastian Schumb (sebastian@sebastains-site.de) + + + window_size + 3000, 3000 + + + category + Custom + + + comment + + + + description + A PD120 SSTV demodulator + + + _enabled + True + + + _coordinate + (8, 8) + + + _rotation + 0 + + + generate_options + no_gui + + + hier_block_src_path + .: + + + id + satnogs_sstv_pd120_demod + + + max_nouts + 0 + + + qt_qss_theme + + + + realtime_scheduling + + + + run_command + {python} -u {filename} + + + run_options + run + + + run + True + + + sizing_mode + fixed + + + thread_safe_setters + + + + title + SSTV PD120 Demodulation + + + placement + (0,0) + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (606, 785) + + + _rotation + 0 + + + id + audio_samp_rate + + + value + 48000 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (223, 793) + + + _rotation + 0 + + + id + deviation + + + value + 5000 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (741, 785) + + + _rotation + 0 + + + id + filter_rate + + + value + 250000 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (318, 793) + + + _rotation + 0 + + + id + max_modulation_freq + + + value + 3000 + + + + variable + + comment + SDR device +TX sampling rate + + + _enabled + True + + + _coordinate + (478, 745) + + + _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 + (837, 785) + + + _rotation + 0 + + + id + xlate_filter_taps + + + value + firdes.low_pass(1, samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76) + + + + analog_nbfm_rx + + audio_rate + 12000 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (877, 562) + + + _rotation + 180 + + + id + analog_nbfm_rx_0 + + + max_dev + 600 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + quad_rate + 12000 + + + tau + 75e-6 + + + + analog_quadrature_demod_cf + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (1252, 291) + + + _rotation + 0 + + + gain + (2*math.pi*deviation)/audio_samp_rate + + + id + analog_quadrature_demod_cf_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (422, 945) + + + _rotation + 0 + + + id + antenna + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + satnogs.not_set_antenna + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (334, 945) + + + _rotation + 0 + + + id + bb_gain + + + label + + + + short_id + + + + hide + none + + + type + eng_float + + + value + satnogs.not_set_rx_bb_gain + + + + rational_resampler_xxx + + alias + + + + comment + + + + affinity + + + + decim + 125 + + + _enabled + True + + + fbw + 0 + + + _coordinate + (837, 267) + + + _rotation + 0 + + + id + blks2_rational_resampler_xxx_1 + + + interp + 24 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + taps + [] + + + type + ccc + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (741, 945) + + + _rotation + 0 + + + id + decoded_data_file_path + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + /tmp/.satnogs/data/data + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (47, 945) + + + _rotation + 0 + + + id + dev_args + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + satnogs.not_set_dev_args + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (47, 865) + + + _rotation + 0 + + + id + doppler_correction_per_sec + + + label + + + + short_id + + + + hide + none + + + type + intx + + + value + 20 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (510, 945) + + + _rotation + 0 + + + id + enable_iq_dump + + + label + + + + short_id + + + + hide + none + + + type + intx + + + value + 0 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (534, 865) + + + _rotation + 180 + + + id + file_path + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + test.ogg + + + + freq_xlating_fir_filter_xxx + + alias + + + + center_freq + lo_offset + + + comment + + + + affinity + + + + decim + int(samp_rate_rx/filter_rate) + + + _enabled + 1 + + + _coordinate + (566, 267) + + + _rotation + 0 + + + id + freq_xlating_fir_filter_xxx_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + samp_rate_rx + + + taps + xlate_filter_taps + + + type + ccc + + + + freq_xlating_fir_filter_xxx + + alias + + + + center_freq + 1750 + + + comment + + + + affinity + + + + decim + 4 + + + _enabled + True + + + _coordinate + (1076, 562) + + + _rotation + 180 + + + id + freq_xlating_fir_filter_xxx_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + taps + 63 + + + type + 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 + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (247, 945) + + + _rotation + 0 + + + id + if_gain + + + label + + + + short_id + + + + hide + none + + + type + eng_float + + + value + satnogs.not_set_rx_if_gain + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (630, 945) + + + _rotation + 0 + + + id + iq_file_path + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + /tmp/iq.dat + + + + parameter + + alias + + + + comment + To avoid the SDR carrier at the DC +we shift the LO a little further + + + _enabled + True + + + _coordinate + (909, 865) + + + _rotation + 0 + + + id + lo_offset + + + label + + + + short_id + + + + hide + none + + + type + eng_float + + + value + 100e3 + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + Using the Carson bandwidth rule for filter width: +width = 2*(deviation + max_modulation_freq). +For the majority of FM transmissions we can expect +max_modulation_freq = 3000 + + + affinity + + + + cutoff_freq + deviation+max_modulation_freq + + + decim + 1 + + + _enabled + True + + + type + fir_filter_ccf + + + _coordinate + (1060, 243) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_samp_rate + + + width + 3000 + + + win + firdes.WIN_HAMMING + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + 1500 + + + decim + 1 + + + _enabled + True + + + type + fir_filter_fff + + + _coordinate + (693, 538) + + + _rotation + 180 + + + gain + 1 + + + id + low_pass_filter_0_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + 12000 + + + width + 1000 + + + win + firdes.WIN_HAMMING + + + + osmosdr_source + + alias + + + + ant0 + satnogs.handle_rx_antenna(rx_sdr_device, antenna) + + + bb_gain0 + satnogs.handle_rx_bb_gain(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.handle_rx_if_gain(rx_sdr_device, if_gain) + + + iq_balance_mode0 + 0 + + + gain0 + satnogs.handle_rx_rf_gain(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.handle_rx_dev_args(rx_sdr_device, dev_args) + + + _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 + (805, 865) + + + _rotation + 0 + + + id + ppm + + + label + + + + short_id + + + + hide + none + + + type + intx + + + value + 0 + + + + rational_resampler_xxx + + alias + + + + comment + + + + affinity + + + + decim + 12000 + + + _enabled + True + + + fbw + 0 + + + _coordinate + (494, 562) + + + _rotation + 180 + + + id + rational_resampler_xxx_0 + + + interp + 5263 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + taps + + + + type + fff + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (151, 945) + + + _rotation + 0 + + + id + rf_gain + + + label + + + + short_id + + + + hide + none + + + type + eng_float + + + value + satnogs.not_set_rx_rf_gain + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (334, 865) + + + _rotation + 0 + + + id + rigctl_port + + + label + + + + short_id + + + + hide + none + + + type + intx + + + value + 4532 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (438, 865) + + + _rotation + 0 + + + id + rx_freq + + + label + + + + short_id + + + + hide + none + + + type + eng_float + + + value + 100e6 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (215, 865) + + + _rotation + 0 + + + id + rx_sdr_device + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + usrpb200 + + + + satnogs_coarse_doppler_correction_cc + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (318, 263) + + + _rotation + 0 + + + id + satnogs_coarse_doppler_correction_cc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + sampling_rate + samp_rate_rx + + + target_freq + rx_freq + + + + satnogs_iq_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + filename + iq_file_path + + + _coordinate + (1060, 155) + + + _rotation + 0 + + + id + satnogs_iq_sink_0 + + + scale + 32767 + + + status + enable_iq_dump + + + + satnogs_ogg_encoder + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + filename + file_path + + + _coordinate + (1531, 275) + + + _rotation + 0 + + + id + satnogs_ogg_encoder_0 + + + quality + 1.0 + + + samp_rate + audio_samp_rate + + + + satnogs_sstv_pd120_sink + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (263, 586) + + + _rotation + 180 + + + id + satnogs_sstv_pd120_sink_0 + + + filename_png + decoded_data_file_path + + + + 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/doppler_correction_per_sec + + + + satnogs_waterfall_sink + + alias + + + + center_freq + 0.0 + + + comment + + + + affinity + + + + _enabled + True + + + fft_size + 1024 + + + filename + waterfall_file_path + + + _coordinate + (1060, 3) + + + _rotation + 0 + + + id + satnogs_waterfall_sink_0 + + + mode + 1 + + + pps + 10 + + + samp_rate + audio_samp_rate + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (645, 865) + + + _rotation + 0 + + + id + waterfall_file_path + + + label + + + + short_id + + + + hide + none + + + type + string + + + value + /tmp/waterfall.dat + + + + analog_nbfm_rx_0 + low_pass_filter_0_0 + 0 + 0 + + + analog_quadrature_demod_cf_0 + hilbert_fc_0 + 0 + 0 + + + analog_quadrature_demod_cf_0 + satnogs_ogg_encoder_0 + 0 + 0 + + + blks2_rational_resampler_xxx_1 + low_pass_filter_0 + 0 + 0 + + + blks2_rational_resampler_xxx_1 + satnogs_iq_sink_0 + 0 + 0 + + + blks2_rational_resampler_xxx_1 + satnogs_waterfall_sink_0 + 0 + 0 + + + freq_xlating_fir_filter_xxx_0 + blks2_rational_resampler_xxx_1 + 0 + 0 + + + freq_xlating_fir_filter_xxx_0_0 + analog_nbfm_rx_0 + 0 + 0 + + + hilbert_fc_0 + freq_xlating_fir_filter_xxx_0_0 + 0 + 0 + + + low_pass_filter_0 + analog_quadrature_demod_cf_0 + 0 + 0 + + + low_pass_filter_0_0 + rational_resampler_xxx_0 + 0 + 0 + + + osmosdr_source_0 + satnogs_coarse_doppler_correction_cc_0 + 0 + 0 + + + rational_resampler_xxx_0 + satnogs_sstv_pd120_sink_0 + 0 + 0 + + + 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/grc/CMakeLists.txt b/grc/CMakeLists.txt index 01034c8..d56f76a 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -24,7 +24,7 @@ list(APPEND debug_blocks satnogs_debug_msg_source.xml satnogs_debug_msg_source_raw.xml satnogs_leo_channel.xml - satnogs_cw_encoder.xml + satnogs_cw_encoder.xml ) list(APPEND enabled_blocks @@ -36,11 +36,11 @@ list(APPEND enabled_blocks satnogs_fox_telem_mm.xml satnogs_frame_file_sink.xml satnogs_iq_sink.xml - satnogs_lrpt_decoder.xml - satnogs_lrpt_sync.xml + satnogs_lrpt_decoder.xml + satnogs_lrpt_sync.xml satnogs_morse_decoder.xml satnogs_multi_format_msg_sink.xml - satnogs_ogg_encoder.xml + satnogs_ogg_encoder.xml satnogs_cw_to_symbol.xml satnogs_udp_msg_source.xml satnogs_tcp_rigctl_msg_source.xml @@ -53,6 +53,7 @@ list(APPEND enabled_blocks satnogs_noaa_apt_sink.xml satnogs_whitening.xml satnogs_frame_acquisition.xml + satnogs_sstv_pd120_sink.xml ) if(${INCLUDE_DEBUG_BLOCKS}) 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/grc/satnogs_sstv_pd120_sink.xml b/grc/satnogs_sstv_pd120_sink.xml new file mode 100644 index 0000000..077853c --- /dev/null +++ b/grc/satnogs_sstv_pd120_sink.xml @@ -0,0 +1,17 @@ + + SSTV PD120 sink + satnogs_sstv_pd120_sink + [satnogs] + import satnogs + satnogs.sstv_pd120_sink($filename_png) + + Output PNG Filename + filename_png + + file_save + + + in + float + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 7af04b4..0ec4861 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -24,7 +24,7 @@ list(APPEND DEBUG_HEADER_FILES morse_debug_source.h debug_msg_source_raw.h debug_msg_source.h - cw_encoder.h + cw_encoder.h ) list(APPEND HEADER_FILES @@ -37,7 +37,7 @@ list(APPEND HEADER_FILES morse.h morse_decoder.h multi_format_msg_sink.h - ogg_encoder.h + ogg_encoder.h cw_to_symbol.h utils.h udp_msg_source.h @@ -59,6 +59,7 @@ list(APPEND HEADER_FILES noaa_apt_sink.h frame_file_sink.h iq_sink.h + sstv_pd120_sink.h ) if(${INCLUDE_DEBUG_BLOCKS}) @@ -76,4 +77,4 @@ install(FILES frame_acquisition.h shift_reg.h golay24.h DESTINATION include/satnogs -) \ No newline at end of file +) diff --git a/include/satnogs/ax25.h b/include/satnogs/ax25.h index 1c0d543..9971c72 100644 --- a/include/satnogs/ax25.h +++ b/include/satnogs/ax25.h @@ -197,7 +197,10 @@ namespace gr out[i++] = fcs & 0xFF; out[i++] = (fcs >> 8) & 0xFF; memset (out + i, AX25_SYNC_FLAG, postamble_len); - + for(size_t j = preamble_len; j < i; j++) { + printf("0x%02x ", out[j]); + } + printf("\n"); return i + postamble_len; } 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 //! + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + + +#ifndef INCLUDED_SATNOGS_SSTV_PD120_SINK_H +#define INCLUDED_SATNOGS_SSTV_PD120_SINK_H + +#include +#include + +namespace gr { + namespace satnogs { + + /*! + * \brief <+description of block+> + * \ingroup satnogs + * + */ + class SATNOGS_API sstv_pd120_sink : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of satnogs::sstv_pd120_sink. + * + * To avoid accidental use of raw pointers, satnogs::sstv_pd120_sink's + * constructor is in a private implementation + * class. satnogs::sstv_pd120_sink::make is the public interface for + * creating new instances. + */ + static sptr make(const char *filename_png); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_SSTV_PD120_SINK_H */ diff --git a/lib/.clang_complete b/lib/.clang_complete new file mode 100644 index 0000000..b817a53 --- /dev/null +++ b/lib/.clang_complete @@ -0,0 +1 @@ +-I.. diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 998fa24..e71ce2d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -74,7 +74,8 @@ list(APPEND satnogs_sources lrpt_decoder_impl.cc frame_acquisition_impl.cc shift_reg.cc - golay24.cc) + golay24.cc + sstv_pd120_sink_impl.cc) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) diff --git a/lib/ax25_decoder_bm_impl.cc b/lib/ax25_decoder_bm_impl.cc index 7b84a09..2dd8b2a 100644 --- a/lib/ax25_decoder_bm_impl.cc +++ b/lib/ax25_decoder_bm_impl.cc @@ -2,7 +2,7 @@ /* * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module * - * Copyright (C) 2016, 2017, 2018 + * Copyright (C) 2016-2019 * Libre Space Foundation * * This program is free software: you can redistribute it and/or modify @@ -30,446 +30,299 @@ namespace gr { - namespace satnogs - { +namespace satnogs +{ - ax25_decoder_bm::sptr - ax25_decoder_bm::make (const std::string& addr, uint8_t ssid, bool promisc, - bool descramble, size_t max_frame_len) - { - return gnuradio::get_initial_sptr ( - new ax25_decoder_bm_impl (addr, ssid, promisc, descramble, - max_frame_len)); - } +ax25_decoder_bm::sptr +ax25_decoder_bm::make (const std::string &addr, uint8_t ssid, bool promisc, + bool descramble, size_t max_frame_len) +{ + return gnuradio::get_initial_sptr ( + new ax25_decoder_bm_impl (addr, ssid, promisc, descramble, max_frame_len)); +} - /* - * 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) : - 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_state (NO_SYNC), - d_shift_reg (0x0), - d_dec_b (0x0), - d_prev_bit_nrzi (0), - d_received_bytes (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")); - /* - * Valid invalid (wrong CRC, different destination Callsign/SSID, - * wrong frame size)PDUs output message port - */ - message_port_register_out (pmt::mp ("failed_pdu")); - } +/* + * 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) : + 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_state (NO_SYNC), + d_shift_reg (0x0), + d_dec_b (0x0), + d_prev_bit_nrzi (0), + d_received_bytes (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)]), + d_start_idx(0) +{ + /* Valid PDUs output message port */ + message_port_register_out (pmt::mp ("pdu")); + /* + * Valid invalid (wrong CRC, different destination Callsign/SSID, + * wrong frame size)PDUs output message port + */ + message_port_register_out (pmt::mp ("failed_pdu")); +} - size_t - ax25_decoder_bm_impl::descramble_and_decode (const uint8_t* in, - size_t nitems) - { - size_t i; - uint8_t descr_bit; - uint8_t dec_bit; - switch (d_state) - { - case NO_SYNC: - for (i = 0; i < nitems; i++) { - descramble_and_decode_1b (in[i]); - if (d_shift_reg == AX25_SYNC_FLAG) { - enter_sync_state (); - return i + 1; - } +void +ax25_decoder_bm_impl::decode () +{ + while (1) { + bool cont = false; + switch (d_state) + { + case NO_SYNC: + for (size_t i = 0; i < d_bitstream.size (); i++) { + decode_1b (d_bitstream[i]); + if (d_shift_reg == AX25_SYNC_FLAG) { + d_bitstream.erase (d_bitstream.begin (), + d_bitstream.begin () + i + 1); + enter_sync_state (); + d_start_idx = 0; + cont = true; + break; } - return nitems; - case IN_SYNC: - /* - * Most of the transmitters repeat several times the AX.25 SYNC - * In case of G3RUH this is mandatory to allow the self synchronizing - * scrambler to settle - */ - for (i = 0; i < nitems; i++) { - descramble_and_decode_1b (in[i]); - d_decoded_bits++; - if(d_decoded_bits == 8) { - /* Perhaps we are in frame! */ - if(d_shift_reg != AX25_SYNC_FLAG) { - enter_decoding_state(); - return i+1; - } - d_decoded_bits = 0; - } - } - return nitems; - case DECODING: - for (i = 0; i < nitems; i++) { - descramble_and_decode_1b (in[i]); - if (d_shift_reg == AX25_SYNC_FLAG) { - LOG_DEBUG("Found frame end"); - enter_frame_end(); - return i+1; - } - else if ((d_shift_reg & 0xfc) == 0x7c) { - /*This was a stuffed bit */ - d_dec_b <<= 1; - } - else if((d_shift_reg & 0xfe) == 0xfe) { - LOG_DEBUG("Invalid shift register value %u", d_received_bytes); - reset_state (); - return i+1; - } - else{ - d_decoded_bits++; - if(d_decoded_bits == 8) { - /* Check if the received byte is valid */ - if(!check_byte()) { - reset_state (); - return i + 1; - } - d_frame_buffer[d_received_bytes] = d_dec_b; - d_received_bytes++; - d_decoded_bits = 0; - - /*Check if the frame limit was reached */ - if (d_received_bytes >= d_max_frame_len) { - LOG_DEBUG("Wrong size"); - message_port_pub ( - pmt::mp ("failed_pdu"), - pmt::make_blob (d_frame_buffer, d_max_frame_len)); - reset_state (); - return i+1; - } - } - } - } - return nitems; - case FRAME_END: - for (i = 0; i < nitems; i++) { - descramble_and_decode_1b (in[i]); - d_decoded_bits++; - if (d_decoded_bits == 8) { - /* Repetitions of the trailing SYNC flag finished */ - if (d_shift_reg != AX25_SYNC_FLAG) { - reset_state(); - return i + 1; - } - d_decoded_bits = 0; - } - } - return nitems; - default: - LOG_ERROR("Invalid decoding state"); - reset_state(); - return nitems; } - } - - size_t - ax25_decoder_bm_impl::decode (const uint8_t* in, size_t nitems) - { - size_t i; - uint8_t descr_bit; - uint8_t dec_bit; - switch (d_state) - { - case NO_SYNC: - for (i = 0; i < nitems; i++) { - decode_1b (in[i]); - if (d_shift_reg == AX25_SYNC_FLAG) { - enter_sync_state (); - return i + 1; - } - } - return nitems; - case IN_SYNC: - /* - * Most of the transmitters repeat several times the AX.25 SYNC - * In case of G3RUH this is mandatory to allow the self synchronizing - * scrambler to settle - */ - for (i = 0; i < nitems; i++) { - decode_1b (in[i]); - d_decoded_bits++; - if (d_decoded_bits == 8) { - /* Perhaps we are in frame! */ - if (d_shift_reg != AX25_SYNC_FLAG) { - enter_decoding_state (); - return i + 1; - } - d_decoded_bits = 0; - } - } - return nitems; - case DECODING: - for (i = 0; i < nitems; i++) { - decode_1b (in[i]); - if (d_shift_reg == AX25_SYNC_FLAG) { - enter_frame_end (); - return i + 1; - } - else if ((d_shift_reg & 0xfc) == 0x7c) { - /*This was a stuffed bit */ - d_dec_b <<= 1; - } - else if ((d_shift_reg & 0xfe) == 0xfe) { - LOG_DEBUG("Invalid shift register value"); - reset_state (); - return i + 1; - } - else { - d_decoded_bits++; - if (d_decoded_bits == 8) { - /* Check if the received byte is valid */ - if(!check_byte()) { - reset_state (); - return i + 1; - } - d_frame_buffer[d_received_bytes] = d_dec_b; - d_received_bytes++; - d_decoded_bits = 0; - - /*Check if the frame limit was reached */ - if (d_received_bytes >= d_max_frame_len) { - LOG_DEBUG("Wrong size"); - message_port_pub ( - pmt::mp ("failed_pdu"), - pmt::make_blob (d_frame_buffer, d_max_frame_len)); - reset_state (); - return i + 1; - } - } - } - } - return nitems; - case FRAME_END: - for (i = 0; i < nitems; i++) { - decode_1b (in[i]); - d_decoded_bits++; - if (d_decoded_bits == 8) { - /* Repetitions of the trailing SYNC flag finished */ - if (d_shift_reg != AX25_SYNC_FLAG) { - reset_state (); - return i + 1; - } - d_decoded_bits = 0; - } - } - return nitems; - default: - LOG_ERROR("Invalid decoding state"); - reset_state (); - return nitems; + if(cont) { + continue; } - } - - /* - * Our virtual destructor. - */ - ax25_decoder_bm_impl::~ax25_decoder_bm_impl () - { - delete [] d_frame_buffer; - } - - void - ax25_decoder_bm_impl::reset_state () - { - d_state = NO_SYNC; - d_dec_b = 0x0; - d_shift_reg = 0x0; - d_decoded_bits = 0; - d_received_bytes = 0; - d_prev_bit_nrzi = 0; - } - - void - ax25_decoder_bm_impl::enter_sync_state () - { - d_state = IN_SYNC; - d_dec_b = 0x0; - d_shift_reg = 0x0; - d_decoded_bits = 0; - d_received_bytes = 0; - } - - void - ax25_decoder_bm_impl::enter_decoding_state () - { - uint8_t tmp; - d_state = DECODING; - d_decoded_bits = 0; - d_shift_reg = 0x0; - - /* - * Due to the possibility of bit stuffing on the first byte some special - * handling is necessary - */ - tmp = d_dec_b; - d_dec_b = 0x0; - for (size_t i = 0; i < 8; i++) { - d_shift_reg = (d_shift_reg >> 1) | (((tmp >> i) & 0x1) << 7); - d_dec_b = (d_dec_b >> 1) | (((tmp >> i) & 0x1) << 7); - if ((d_shift_reg & 0xfc) == 0x7c) { - /*This was a stuffed bit */ - d_dec_b <<= 1; - } - else{ + d_bitstream.clear (); + return; + case IN_SYNC: + /* + * Most of the transmitters repeat several times the AX.25 SYNC + * In case of G3RUH this is mandatory to allow the self synchronizing + * scrambler to settle + */ + for (size_t i = d_start_idx; i < d_bitstream.size (); i++) { + decode_1b (d_bitstream[i]); d_decoded_bits++; + if (d_decoded_bits == 8) { + /* Perhaps we are in frame! */ + if (d_shift_reg != AX25_SYNC_FLAG) { + d_start_idx = i + 1; + enter_decoding_state (); + cont = true; + break; + } + d_decoded_bits = 0; + } } - } + if(cont) { + continue; + } + d_start_idx = d_bitstream.size (); + return; + case DECODING: + for (size_t i = d_start_idx; i < d_bitstream.size (); i++) { + decode_1b (d_bitstream[i]); + if (d_shift_reg == AX25_SYNC_FLAG) { + LOG_DEBUG("Found frame end"); + if (enter_frame_end ()) { + d_bitstream.erase (d_bitstream.begin (), + d_bitstream.begin () + i + 1); + } + cont = true; + break; + } + else if ((d_shift_reg & 0xfc) == 0x7c) { + /*This was a stuffed bit */ + d_dec_b <<= 1; + } + else if ((d_shift_reg & 0xfe) == 0xfe) { + LOG_DEBUG("Invalid shift register value %u", d_received_bytes); + reset_state (); + cont = true; + break; + } + else { + d_decoded_bits++; + if (d_decoded_bits == 8) { + d_frame_buffer[d_received_bytes++] = d_dec_b; + d_decoded_bits = 0; - if(d_decoded_bits == 8) { - d_frame_buffer[0] = d_dec_b; - d_decoded_bits = 0; - d_received_bytes = 1; - } - else { - d_received_bytes = 0; - } - - } - - void - ax25_decoder_bm_impl::enter_frame_end () - { - uint16_t fcs; - uint16_t recv_fcs = 0x0; - - /* First check if the size of the frame is valid */ - if (d_received_bytes < AX25_MIN_ADDR_LEN + sizeof(uint16_t)) { - d_dec_b = 0x0; - d_shift_reg = 0x0; - d_decoded_bits = 0; - d_received_bytes = 0; - d_state = FRAME_END; + /*Check if the frame limit was reached */ + if (d_received_bytes >= d_max_frame_len) { + LOG_DEBUG("Wrong size"); + reset_state (); + cont = true; + break; + } + } + } + } + if(cont) { + continue; + } + d_start_idx = d_bitstream.size (); + return; + default: + LOG_ERROR("Invalid decoding state"); + reset_state (); 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]; +/* + * Our virtual destructor. + */ +ax25_decoder_bm_impl::~ax25_decoder_bm_impl () +{ + delete[] d_frame_buffer; + LOG_DEBUG("Left over: %lu", d_bitstream.size()); +} - if (fcs == recv_fcs) { - 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_DEBUG("Wrong crc"); - } - d_dec_b = 0x0; - d_shift_reg = 0x0; - d_decoded_bits = 0; - d_received_bytes = 0; - d_state = FRAME_END; - } +void +ax25_decoder_bm_impl::reset_state () +{ + d_state = NO_SYNC; + d_dec_b = 0x0; + d_shift_reg = 0x0; + d_decoded_bits = 0; + d_received_bytes = 0; +} - /** - * Performs descrambling and NRZI decoding of an input bit. - * The decoded bit is then shifted in front of the d_shift_reg and the d_dec_b - * variables. This shift in front is due to the LS bit first transmission - * of the Ax.25 protocol. - * - * @param in input bit - */ - inline void - ax25_decoder_bm_impl::descramble_and_decode_1b (uint8_t in) - { - uint8_t descr_bit; - uint8_t dec_bit; +void +ax25_decoder_bm_impl::enter_sync_state () +{ + d_state = IN_SYNC; + d_dec_b = 0x0; + d_shift_reg = 0x0; + d_decoded_bits = 0; + d_received_bytes = 0; +} - in &= 0x1; +void +ax25_decoder_bm_impl::enter_decoding_state () +{ + uint8_t tmp; + d_state = DECODING; + d_decoded_bits = 0; + d_received_bytes = 0; + /* + * Due to the possibility of bit stuffing on the first byte some special + * handling is necessary + */ + if ((d_shift_reg & 0xfc) == 0x7c) { + /*This was a stuffed bit */ + d_dec_b <<= 1; + d_decoded_bits = 7; + } + else { + d_frame_buffer[0] = d_dec_b; + d_decoded_bits = 0; + d_received_bytes = 1; + } +} + +bool +ax25_decoder_bm_impl::enter_frame_end () +{ + uint16_t fcs; + uint16_t recv_fcs = 0x0; + + /* First check if the size of the frame is valid */ + if (d_received_bytes < AX25_MIN_ADDR_LEN + sizeof(uint16_t)) { + reset_state (); + return false; + } + + /* + * Check if the frame is correct using the FCS field + * Using this field also try to correct up to 2 error bits + */ + if (frame_check ()) { + message_port_pub ( + pmt::mp ("pdu"), + pmt::make_blob (d_frame_buffer, d_received_bytes - sizeof(uint16_t))); + reset_state (); + return true; + } + else { + message_port_pub ( + pmt::mp ("failed_pdu"), + pmt::make_blob (d_frame_buffer, d_received_bytes - sizeof(uint16_t))); + LOG_DEBUG("Wrong crc"); + reset_state (); + return false; + } +} + + +inline void +ax25_decoder_bm_impl::decode_1b (uint8_t in) +{ + + /* In AX.25 the LS bit is sent first */ + d_shift_reg = (d_shift_reg >> 1) | (in << 7); + d_dec_b = (d_dec_b >> 1) | (in << 7); +} + +bool +ax25_decoder_bm_impl::frame_check () +{ + uint16_t fcs; + uint16_t recv_fcs = 0x0; + uint8_t orig_byte; + + /* 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]; + if (fcs == recv_fcs) { + return true; + } + return false; +} + +int +ax25_decoder_bm_impl::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int ret; + const uint8_t *in = (const uint8_t*) input_items[0]; + + if (noutput_items < 1) { + return noutput_items; + } + + + if (d_descramble) { + for (int i = 0; i < noutput_items; i++) { /* Perform NRZI decoding */ - dec_bit = (~((in - d_prev_bit_nrzi) % 2)) & 0x1; - d_prev_bit_nrzi = in; - - - /* Descramble the input bit */ - descr_bit = d_lfsr.next_bit_descramble (dec_bit); - - /* In AX.25 the LS bit is sent first */ - d_shift_reg = (d_shift_reg >> 1) | (descr_bit << 7); - d_dec_b = (d_dec_b >> 1) | (descr_bit << 7); + uint8_t b = (~((in[i] - d_prev_bit_nrzi) % 2)) & 0x1; + d_prev_bit_nrzi = in[i]; + b = d_lfsr.next_bit_descramble (b); + d_bitstream.push_back (b); } - - inline void - ax25_decoder_bm_impl::decode_1b (uint8_t in) - { - uint8_t dec_bit; - in &= 0x1; - + } + else { + for (int i = 0; i < noutput_items; i++) { /* Perform NRZI decoding */ - dec_bit = (~((in - d_prev_bit_nrzi) % 2)) & 0x1; - d_prev_bit_nrzi = in; - - /* 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); + uint8_t b = (~((in[i] - d_prev_bit_nrzi) % 2)) & 0x1; + d_prev_bit_nrzi = in[i]; + d_bitstream.push_back (b); } + } + decode(); + return noutput_items; +} - /** - * Checks if a AX.25 decoded byte is valid. This actually can be checked - * only in the address field, where all fields should have the LS bit - * set to zero. - * @returns true if the decoded byte is valid, false otherwise - */ - inline bool - ax25_decoder_bm_impl::check_byte () - { - if(d_received_bytes < AX25_MIN_ADDR_LEN - 1) { - if(d_dec_b & 0x1) { - return false; - } - } - else if(d_received_bytes == AX25_MIN_ADDR_LEN - 1) { - if(d_dec_b & 0x1) { - return true; - } - return false; - } - return true; - } - - - int - ax25_decoder_bm_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - int ret; - const uint8_t *in = (const uint8_t *) input_items[0]; - - - if(noutput_items < 1) { - return noutput_items; - } - if (d_descramble) { - ret = descramble_and_decode (in, noutput_items); - } - else { - ret = decode (in, noutput_items); - } - return ret; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/ax25_decoder_bm_impl.h b/lib/ax25_decoder_bm_impl.h index 637e6ce..a6f1eab 100644 --- a/lib/ax25_decoder_bm_impl.h +++ b/lib/ax25_decoder_bm_impl.h @@ -24,6 +24,7 @@ #include #include +#include namespace gr { @@ -35,7 +36,7 @@ namespace gr private: typedef enum { - NO_SYNC, IN_SYNC, DECODING, FRAME_END + NO_SYNC, IN_SYNC, DECODING } decoding_state_t; /** @@ -53,6 +54,8 @@ namespace gr size_t d_decoded_bits; digital::lfsr d_lfsr; uint8_t *d_frame_buffer; + std::deque d_bitstream; + size_t d_start_idx; void reset_state (); @@ -60,20 +63,16 @@ namespace gr enter_sync_state (); void enter_decoding_state (); - void + bool enter_frame_end (); - size_t - descramble_and_decode (const uint8_t *in, size_t nitems); - size_t - decode (const uint8_t *in, size_t nitems); + void + decode (); - inline void - descramble_and_decode_1b (uint8_t in); inline void decode_1b (uint8_t in); - inline bool - check_byte (); + bool + frame_check(); public: diff --git a/lib/cw_to_symbol_impl.cc b/lib/cw_to_symbol_impl.cc index 1b36921..3d5648a 100644 --- a/lib/cw_to_symbol_impl.cc +++ b/lib/cw_to_symbol_impl.cc @@ -31,322 +31,342 @@ #include #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 */ diff --git a/lib/sstv_pd120_sink_impl.cc b/lib/sstv_pd120_sink_impl.cc new file mode 100644 index 0000000..d3674bd --- /dev/null +++ b/lib/sstv_pd120_sink_impl.cc @@ -0,0 +1,210 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2018, 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "sstv_pd120_sink_impl.h" + +namespace gr { + namespace satnogs { + + const size_t image_width = 640; + const size_t image_height = 496; + const size_t sync_length = 105; + const size_t sync_thresh = 100; + const size_t porch_length = 10; + const size_t line_length = sync_length + porch_length + 4 * image_width; + + const float max_dev = 600; + const float center = 1750; + const float min_freq = 1200; + const float max_freq = 2300; + + const float color_low = 1500; + const float color_high = max_freq; + + + sstv_pd120_sink::sptr + sstv_pd120_sink::make(const char *filename_png) + { + return gnuradio::get_initial_sptr + (new sstv_pd120_sink_impl(filename_png)); + } + + /* + * The private constructor + */ + sstv_pd120_sink_impl::sstv_pd120_sink_impl(const char *filename_png) + : gr::sync_block("sstv_pd120_sink", + gr::io_signature::make (1, 1, sizeof(float)), + gr::io_signature::make (0, 0, 0)), + d_filename_png (filename_png), + d_has_sync(false), + d_initial_sync(true), + d_line_pos(0), + d_image_y (0), + d_num_image(0) + { + set_history(sync_length); + d_line = new float[line_length]; + d_image = png::image(image_width, image_height); + } + + /* + * Our virtual destructor. + */ + sstv_pd120_sink_impl::~sstv_pd120_sink_impl() + { + delete[] d_line; + } + + float + sstv_pd120_sink_impl::to_frequency(float sample) { + float freq = center + sample * max_dev; + freq = std::max(min_freq, freq); + freq = std::min(max_freq, freq); + return freq; + } + + int + sstv_pd120_sink_impl::to_color(float sample) { + sample = (sample - color_low) / (color_high - color_low); + sample = sample * 255.0f; + sample = std::max(sample, 0.0f); + sample = std::min(sample, 255.0f); + return int(sample); + } + + void + sstv_pd120_sink_impl::ycbcr_to_rgb(int ycbcr[3], int rgb[3]) { + int y = ycbcr[0]; + int cb = ycbcr[1]; + int cr = ycbcr[2]; + + //https://stackoverflow.com/questions/4041840/function-to-convert-ycbcr-to-rgb/15333019#15333019 + cr = cr - 128; + cb = cb - 128; + int r = y + 45 * cr / 32; + int g = y - (11 * cb + 23 * cr) / 32; + int b = y + 113 * cb / 64; + + rgb[0] = std::min(255, std::max(r, 0)); + rgb[1] = std::min(255, std::max(g, 0)); + rgb[2] = std::min(255, std::max(b, 0)); + } + + bool + sstv_pd120_sink_impl::is_sync(size_t pos, const float *samples) { + size_t count = 0; + for(size_t i = 0; i < sync_length; i++) { + float sample = to_frequency(samples[pos - (sync_length - 1) + i]); + //std::cout << sample << std::endl; + if(sample < color_low) { + count += 1; + } + } + + bool res = count > sync_thresh && !d_has_sync; + d_has_sync = count > sync_thresh; + + if(res) { + d_initial_sync = false; + } + + return res; + } + + + void + sstv_pd120_sink_impl::render_line() { + int start_pos = d_line_pos - sync_length - 4 * image_width; + if(start_pos < 0) { + return; + } + + for(size_t x = 0; x < image_width; x++) { + int y0 = to_color(d_line[start_pos + x]); + int cr = to_color(d_line[start_pos + image_width + x]); + int cb = to_color(d_line[start_pos + 2 * image_width + x]); + int y1 = to_color(d_line[start_pos + 3 * image_width + x]); + + int rgb0[3] = {0, 0, 0}; + int ycrcb0[] = {y0, cb, cr}; + ycbcr_to_rgb(ycrcb0, rgb0); + + d_image.set_pixel(x, d_image_y, png::rgb_pixel(rgb0[0], rgb0[1], rgb0[2])); + + int rgb1[] = {0, 0, 0}; + int ycrcb1[] = {y1, cb, cr}; + ycbcr_to_rgb(ycrcb1, rgb1); + d_image.set_pixel(x, d_image_y + 1, png::rgb_pixel(rgb1[0], rgb1[1], rgb1[2])); + } + + std::string file_name = std::string(d_filename_png) + "_" + std::to_string(d_num_image) + ".png"; + std::cout << "Writing " << file_name << std::endl; + d_image.write(file_name.c_str()); + + std::cout << "Line number: " << d_image_y << std::endl; + + d_image_y += 2; + + if(d_image_y >= image_height){ + std::cout << "Finished image, resetting." << std::endl; + d_image_y = 0; + d_initial_sync = true; + d_num_image++; + } + } + + int + sstv_pd120_sink_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + + for (size_t i = sync_length - 1; + i < noutput_items + sync_length - 1; i++) { + + float sample = to_frequency(in[i]); + d_line[d_line_pos] = sample; + d_line_pos++; + + if(is_sync(i, in) || d_line_pos >= line_length) { + if(d_initial_sync) { + d_image_y = 0; + } + else if(!d_initial_sync && d_line_pos > line_length - porch_length) { + std::cout << "Rendering after: " << d_line_pos << std::endl; + render_line(); + } + d_line_pos = 0; + } + } + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace satnogs */ +} /* namespace gr */ diff --git a/lib/sstv_pd120_sink_impl.h b/lib/sstv_pd120_sink_impl.h new file mode 100644 index 0000000..36d734a --- /dev/null +++ b/lib/sstv_pd120_sink_impl.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2018, 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef INCLUDED_SATNOGS_SSTV_PD120_SINK_IMPL_H +#define INCLUDED_SATNOGS_SSTV_PD120_SINK_IMPL_H + +#include + +#define PNG_DEBUG 3 +#include + +namespace gr { + namespace satnogs { + + class sstv_pd120_sink_impl : public sstv_pd120_sink + { + private: + std::string d_filename_png; + bool d_has_sync; + bool d_initial_sync; + + float *d_line; + size_t d_line_pos; + size_t d_image_y; + size_t d_num_image; + + png::image d_image; + + float to_frequency(float sample); + int to_color(float sample); + void ycbcr_to_rgb(int ycbcr[3], int rgb[3]); + bool is_sync(size_t pos, const float *samples); + + void render_line(); + + public: + sstv_pd120_sink_impl(const char *filename_png); + ~sstv_pd120_sink_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_SSTV_PD120_SINK_IMPL_H */ diff --git a/python/hw_settings.py b/python/hw_settings.py index 61eaa75..b3a85fb 100644 --- a/python/hw_settings.py +++ b/python/hw_settings.py @@ -37,13 +37,16 @@ hw_tx_settings = {'usrpb200' : {'rf_gain' : 60.0, 'if_gain' : 0.0, hw_rx_settings = {'usrpb200' : {'rf_gain' : 50.0, 'if_gain' : 0.0, 'bb_gain' : 0.0, 'samp_rate' : 5e5, 'antenna' : 'TX/RX', 'dev_arg': 'uhd'}, + 'usrp1' : {'rf_gain' : 500.0, 'if_gain' : 30.0, + 'bb_gain' : 0.0, 'samp_rate' : 5e5, + 'antenna' : 'RX', 'dev_arg': 'uhd'}, 'usrp2' : {'rf_gain' : 50.0, 'if_gain' : 0.0, 'bb_gain' : 0.0, 'samp_rate' : 5e5, 'antenna' : 'TX/RX', 'dev_arg': 'uhd'}, 'usrpx3x0' : {'rf_gain' : 26.0, 'if_gain' : 0.0, 'bb_gain' : 0.0, 'samp_rate' : 2e6, 'antenna' : 'TX/RX', 'dev_arg': 'uhd'}, - 'airspy' : {'rf_gain' : 30.0, 'if_gain' : 0.0, + 'airspy' : {'rf_gain' : 19.0, 'if_gain' : 0.0, 'bb_gain' : 0.0, 'samp_rate' : 10e6, 'antenna' : '', 'dev_arg': 'airspy'}, 'airspymini' : {'rf_gain' : 15.0, 'if_gain' : 0.0, diff --git a/swig/satnogs_swig0.i b/swig/satnogs_swig0.i index 40d4064..b9933b9 100644 --- a/swig/satnogs_swig0.i +++ b/swig/satnogs_swig0.i @@ -33,6 +33,7 @@ #include "satnogs/ogg_encoder.h" #include "satnogs/ogg_source.h" #include "satnogs/noaa_apt_sink.h" +#include "satnogs/sstv_pd120_sink.h" #include "satnogs/frame_file_sink.h" #include "satnogs/iq_sink.h" #include "satnogs/quad_demod_filter_ff.h" @@ -103,6 +104,9 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, ogg_source); %include "satnogs/noaa_apt_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, noaa_apt_sink); +%include "satnogs/sstv_pd120_sink.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, sstv_pd120_sink); + %include "satnogs/frame_file_sink.h" GR_SWIG_BLOCK_MAGIC2(satnogs, frame_file_sink);