# # Copyright 2005,2006,2007 Free Software Foundation, Inc. # # OP25 Decoder Block # Copyright 2009, 2014 Max H. Parke KA1RBI # # This file is part of GNU Radio and part of OP25 # # This 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, or (at your option) # any later version. # # It 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; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # """ P25 decoding block. """ import time from gnuradio import gr, eng_notation from gnuradio import blocks, audio from gnuradio.eng_option import eng_option import op25 import op25_repeater # default values (used in __init__ and add_options) _def_debug = 0 _def_num_ambe = False _def_do_imbe = True _def_wireshark_host = '' _def_udp_port = 0 _def_dest = 'wav' _def_audio_rate = 8000 _def_audio_output = 'plughw:0,0' _def_max_tdma_timeslots = 2 # ///////////////////////////////////////////////////////////////////////////// # decoder # ///////////////////////////////////////////////////////////////////////////// class p25_decoder_sink_b(gr.hier_block2): def __init__(self, dest = _def_dest, do_imbe = _def_do_imbe, num_ambe = _def_num_ambe, wireshark_host = _def_wireshark_host, udp_port = _def_udp_port, do_msgq = False, msgq = None, audio_output = _def_audio_output, debug = _def_debug, msgq_id = 0): """ Hierarchical block for P25 decoding. @param debug: debug level @type debug: int """ gr.hier_block2.__init__(self, "p25_demod_c", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(0, 0, 0)) # Output signature assert 0 <= num_ambe <= _def_max_tdma_timeslots assert not (num_ambe > 1 and dest != 'wav') self.debug = debug self.dest = dest do_output = False do_audio_output = False do_phase2_tdma = False if dest == 'wav': do_output = True if do_imbe: do_audio_output = True if num_ambe > 0: do_phase2_tdma = True if msgq is None: msgq = gr.msg_queue(1) self.p25_decoders = [] self.audio_s2f = [] self.scaler = [] self.audio_sink = [] self.xorhash = [] num_decoders = 1 if num_ambe > 1: num_decoders += num_ambe - 1 for slot in range(num_decoders): self.p25_decoders.append(op25_repeater.p25_frame_assembler(wireshark_host, udp_port, debug, do_imbe, do_output, do_msgq, msgq, do_audio_output, do_phase2_tdma, msgq_id+slot)) self.p25_decoders[slot].set_slotid(slot) self.xorhash.append('') if dest == 'wav': filename = 'default-%f-%d.wav' % (time.time(), slot) n_channels = 1 sample_rate = 8000 bits_per_sample = 16 self.audio_s2f.append(blocks.short_to_float()) # another ridiculous conversion self.scaler.append(blocks.multiply_const_ff(1 / 32768.0)) self.audio_sink.append(blocks.wavfile_sink(filename, n_channels, sample_rate, bits_per_sample)) self.connect(self, self.p25_decoders[slot], self.audio_s2f[slot], self.scaler[slot], self.audio_sink[slot]) elif dest == 'audio': self.connect(self, self.p25_decoders[slot]) def close_file(self, index=0): if self.dest != 'wav': return self.audio_sink[index].close() def set_slotid(self, slot, index=0): self.p25_decoders[index].set_slotid(slot) def set_output(self, filename, index=0): if self.dest != 'wav': return self.audio_sink[index].open(filename) def set_nac(self, nac, index=0): self.p25_decoders[index].set_nac(nac) def set_xormask(self, xormask, xorhash, index=0): if self.xorhash[index] == xorhash: return self.xorhash[index] = xorhash self.p25_decoders[index].set_xormask(xormask) def set_scaler_k(self, k, index=0): self.scaler[index].set_k(k)