def configure_tdma(self, params): if params['tdma'] is not None and not self.options.phase2_tdma: sys.stderr.write( "***TDMA request for frequency %d failed- phase2_tdma option not enabled\n" % params['freq']) return set_tdma = False if params['tdma'] is not None: set_tdma = True self.decoder.set_slotid(params['tdma']) if set_tdma == self.tdma_state: return # already in desired state self.tdma_state = set_tdma if set_tdma: hash = '%x%x%x' % (params['nac'], params['sysid'], params['wacn']) if hash not in self.xor_cache: self.xor_cache[hash] = lfsr.p25p2_lfsr( params['nac'], params['sysid'], params['wacn']).xor_chars self.decoder.set_xormask(self.xor_cache[hash], hash) self.decoder.set_nac(params['nac']) rate = 6000 else: rate = 4800 sps = self.basic_rate / rate self.demod.set_symbol_rate( rate) # this and the foll. call should be merged? self.demod.clock.set_omega(float(sps))
def configure_tdma(self, params): if params['tdma'] is not None and not self.options.phase2_tdma: sys.stderr.write( "***TDMA request for frequency %d failed- phase2_tdma option not enabled" % params['freq']) return set_tdma = False if params['tdma'] is not None: set_tdma = True self.decoder.set_slotid(params['tdma']) if set_tdma == self.tdma_state: return # already in desired state self.tdma_state = set_tdma if set_tdma: hash = '%x%x%x' % (params['nac'], params['sysid'], params['wacn']) if hash not in self.xor_cache: self.xor_cache[hash] = lfsr.p25p2_lfsr( params['nac'], params['sysid'], params['wacn']).xor_chars self.decoder.set_xormask(self.xor_cache[hash], hash) rate = 6000 else: rate = 4800 self.set_sps(rate) if not self.options.symbols: self.demod.set_omega(rate)
def configure_p25_tdma(self, params): set_tdma = False if 'tdma' in params and params['tdma'] is not None: set_tdma = True self.decoder.set_slotid(params['tdma']) if set_tdma == self.tdma_state: return self.tdma_state = set_tdma if set_tdma: hash = '%x%x%x' % (params['nac'], params['sysid'], params['wacn']) if hash not in self.xor_cache: self.xor_cache[hash] = lfsr.p25p2_lfsr( params['nac'], params['sysid'], params['wacn']).xor_chars if self.verbosity >= 5: sys.stderr.write( "%s [%d] Caching TDMA xor mask for NAC: 0x%x, SYSID: 0x%x, WACN: 0x%x\n" % (log_ts.get(), self.msgq_id, params['nac'], params['sysid'], params['wacn'])) self.decoder.set_xormask(self.xor_cache[hash]) rate = 6000 else: rate = self.config['symbol_rate'] self.symbol_rate = rate self.demod.set_omega(rate) if 'eye' in self.sinks: self.sinks['eye'][0].set_sps(self.config['if_rate'] / rate)
def __init__(self, options): gr.top_block.__init__(self, "mhp") self.lfsr = lfsr.p25p2_lfsr(options.nac, options.sysid, options.wacn) xor_mask = '' for c in self.lfsr.xorsyms: xor_mask += chr(c) IN = blocks.file_source(gr.sizeof_char, options.input_file) slotid = options.tdma_slotid msgq = gr.msg_queue(2) do_msgq = False wireshark_host = '' udp_port = 0 verbosity = 100 do_imbe = 1 do_output = 1 do_msgq = 0 rx_q = gr.msg_queue(1) do_audio_output = 1 phase2_tdma = 1 FRAMER = op25_repeater.p25_frame_assembler(wireshark_host, udp_port, verbosity, do_imbe, do_output, do_msgq, rx_q, do_audio_output, phase2_tdma) FRAMER.set_xormask(xor_mask) S2F = blocks.short_to_float() M = blocks.multiply_const_ff(1.0 / 32767.0) SINK = audio.sink(8000, 'plughw:0,0') self.connect(IN, FRAMER, S2F, M, SINK)
def configure_p25_tdma(self, params): set_tdma = False if 'tdma' in params and params['tdma'] is not None: set_tdma = True self.decoder.set_slotid(params['tdma']) if set_tdma == self.tdma_state: return self.tdma_state = set_tdma if set_tdma: hash = '%x%x%x' % (params['nac'], params['sysid'], params['wacn']) if hash not in self.xor_cache: self.xor_cache[hash] = lfsr.p25p2_lfsr( params['nac'], params['sysid'], params['wacn']).xor_chars self.decoder.set_xormask(self.xor_cache[hash]) rate = 6000 else: rate = self.config['symbol_rate'] self.symbol_rate = rate self.demod.set_omega(rate) if 'eye' in self.sinks: self.sinks['eye'].set_sps(self.config['if_rate'] / rate)
def configure_tdma(self, params): if params['tdma'] is not None and not self.options.phase2_tdma: print '***TDMA request for frequency %d failed- phase2_tdma option not enabled' % params[ 'freq'] return set_tdma = False if params['tdma'] is not None: set_tdma = True if set_tdma == self.tdma_state: return # already in desired state self.tdma_state = set_tdma if set_tdma: self.decoder.set_slotid(params['tdma']) hash = '%x%x%x' % (params['nac'], params['sysid'], params['wacn']) if hash not in self.xor_cache: self.xor_cache[hash] = lfsr.p25p2_lfsr( params['nac'], params['sysid'], params['wacn']).xor_chars self.decoder.set_xormask(self.xor_cache[hash], hash) sps = self.basic_rate / 6000 else: sps = self.basic_rate / 4800 self.demod.clock.set_omega(float(sps))
def configure_tdma(self, params): set_tdma = False if params['tdma'] is not None: set_tdma = True self.decoder.set_slotid(params['tdma']) self.demod.clock.set_tdma(set_tdma) if set_tdma == self.tdma_state: return # already in desired state self.tdma_state = set_tdma if set_tdma: hash = '%x%x%x' % (params['nac'], params['sysid'], params['wacn']) if hash not in self.xor_cache: self.xor_cache[hash] = lfsr.p25p2_lfsr( params['nac'], params['sysid'], params['wacn']).xor_chars self.decoder.set_xormask(self.xor_cache[hash], hash) self.decoder.set_nac(params['nac']) rate = 6000 else: rate = 4800 sps = self.config['if_rate'] / rate self.demod.set_symbol_rate( rate) # this and the foll. call should be merged? self.demod.clock.set_omega(float(sps))
def logging_scheduler(self, curr_time): tsys = self.trunked_systems[self.current_nac] for tgid in tsys.get_updated_talkgroups(curr_time): frequency = tsys.talkgroups[tgid]['frequency'] tdma_slot = tsys.talkgroups[tgid]['tdma_slot'] # see if this tgid active on any other freq(s) other_freqs = [ f for f in self.working_frequencies if f != frequency and tgid in self.working_frequencies[f]['tgids'] ] if other_freqs: print( '%f tgid %d slot %s frequency %d found on other frequencies %s' % (curr_time, tgid, tdma_slot, frequency, ','.join( ['%s' % f for f in other_freqs]))) for f in other_freqs: self.free_talkgroup(f, tgid, curr_time) if not self.working_frequencies[f]['tgids']: self.free_frequency(f, curr_time) diff = abs(tsys.center_frequency - frequency) if diff > self.input_rate / 2: #print '%f request for frequency %d tgid %d failed, offset %d exceeds maximum %d' % (curr_time, frequency, tgid, diff, self.input_rate/2) continue update = True if frequency in self.working_frequencies: tgids = self.working_frequencies[frequency]['tgids'] if tgid in tgids: if tgids[tgid]['tdma_slot'] == tdma_slot: update = False else: print('%f slot switch %s was %s tgid %d frequency %d' % (curr_time, tdma_slot, tgids[tgid]['tdma_slot'], tgid, frequency)) worker = self.working_frequencies[frequency]['worker'] else: #active_tdma_slots = [tgids[tg]['tdma_slot'] for tg in tgids] print( '%f new tgid %d slot %s arriving on already active frequency %d' % (curr_time, tgid, tdma_slot, frequency)) worker = self.working_frequencies[frequency]['worker'] else: worker = self.find_available_worker() if worker is None: print('*** error, no free demodulators, freq %d tgid %d' % (frequency, tgid)) continue self.working_frequencies[frequency] = { 'tgids': {}, 'worker': worker } worker['demod'].set_relative_frequency(tsys.center_frequency - frequency) print('%f starting worker frequency %d tg %d slot %s' % (curr_time, frequency, tgid, tdma_slot)) self.working_frequencies[frequency]['tgids'][tgid] = { 'updated': curr_time, 'tdma_slot': tdma_slot } if not update: continue filename = 'tgid-%d-%f.wav' % (tgid, curr_time) print('%f update frequency %d tg %d slot %s file %s' % (curr_time, frequency, tgid, tdma_slot, filename)) # set demod speed, decoder slot, output file name demod = worker['demod'] decoder = worker['decoder'] symbol_rate = 4800 if tdma_slot is None: index = 0 else: index = tdma_slot symbol_rate = 6000 xorhash = '%x%x%x' % (self.current_nac, tsys.ns_syid, tsys.ns_wacn) if xorhash not in self.xor_cache: self.xor_cache[xorhash] = lfsr.p25p2_lfsr( self.current_nac, tsys.ns_syid, tsys.ns_wacn).xor_chars decoder.set_xormask(self.xor_cache[xorhash], xorhash, index=index) demod.set_omega(symbol_rate) decoder.set_output(filename, index=index) # garbage collection if self.last_garbage_collect + 1 > curr_time: return self.last_garbage_collect = curr_time gc_frequencies = [] gc_tgids = [] for frequency in self.working_frequencies: tgids = self.working_frequencies[frequency]['tgids'] inactive_tgids = [ [frequency, tgid] for tgid in tgids if tgids[tgid]['updated'] + self.TGID_HOLD_TIME < curr_time ] if len(inactive_tgids) == len(tgids): gc_frequencies += [frequency] gc_tgids += inactive_tgids for frequency, tgid in gc_tgids: # expire talkgroups self.free_talkgroup(frequency, tgid, curr_time) for frequency in gc_frequencies: # expire working frequencies self.free_frequency(frequency, curr_time)
def main(): parser = OptionParser() parser.add_option("-v", "--verbose", action="store_true", default=False) parser.add_option("-i", "--input-file", type="string", default=None, help="input file name") parser.add_option("-n", "--nac", type="int", default=0, help="NAC") parser.add_option("-s", "--sysid", type="int", default=0, help="sysid") parser.add_option("-w", "--wacn", type="int", default=0, help="WACN") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) file = options.input_file my_isch = isch.p25p2_isch() my_duid = duid.p25p2_duid() my_lfsr = lfsr.p25p2_lfsr(options.nac, options.sysid, options.wacn) #print 'nac: %d' % options.nac d = open(file).read() symbols = [] for c in d: symbols.append(ord(c)) sync0 = bits_to_dibits(mk_array(0x575d57f7ff, 40)) sync_start = find_sym(sync0, symbols) assert sync_start > 0 # unable to locate any sync sequence superframe = -1 for i in xrange(sync_start, sync_start + (180 * 32), 180): chn, loc, fr, cnt = my_isch.decode_isch(symbols[i:i + 20]) if chn == 0 and loc == 0: superframe = i break assert superframe > 0 # unable to locate start of superframe errors = 0 for i in xrange(superframe, len(symbols) - SUPERFRAME_LEN, SUPERFRAME_LEN): syms1 = symbols[i + 10:i + SUPERFRAME_LEN + 10] syms2 = np.array(syms1) ^ my_lfsr.xorsyms for j in xrange(12): if options.verbose: print '%s superframe %d timeslot %d %s' % ('=' * 20, i, j, '=' * 20) chn, loc, fr, cnt = my_isch.decode_isch(symbols[i + (j * 180):i + (j * 180) + 20]) if chn == -1: if options.verbose: print 'unknown isch codeword at %d' % (i + (j * 180)) errors += 1 elif chn == -2: if options.verbose: print 'sync isch codeword found at %d' % (i + (j * 180)) errors = 0 else: if options.verbose: print "channel %d loc %d fr %d count %d" % (chn, loc, fr, cnt) errors = 0 burst = syms1[(j * 180):(j * 180) + 180] burst_d = syms2[(j * 180):(j * 180) + 180] btype = my_duid.decode_duid(burst) if options.verbose: print 'burst at %d type %s' % (i + (j * 180), btype) if btype == '2v' or btype == '4v': process_v(burst_d, btype) elif not btype.startswith('unknown'): maybe_sync = burst[79:79 + 21] if btype.endswith(' w'): # scrambled burst = burst_d # process_oemi(burst, btype) if errors > 6: if options.verbose: print "too many successive errors, exiting at i=%d" % (i) break
def logging_scheduler(self, curr_time): tsys = self.trunked_systems[self.current_nac] for tgid in tsys.get_updated_talkgroups(curr_time): frequency = tsys.talkgroups[tgid]['frequency'] tdma_slot = tsys.talkgroups[tgid]['tdma_slot'] # see if this tgid active on any other freq(s) other_freqs = [f for f in self.working_frequencies if f != frequency and tgid in self.working_frequencies[f]['tgids']] if other_freqs: print '%f tgid %d slot %s frequency %d found on other frequencies %s' % (curr_time, tgid, tdma_slot, frequency, ','.join(['%s' % f for f in other_freqs])) for f in other_freqs: self.free_talkgroup(f, tgid, curr_time) if not self.working_frequencies[f]['tgids']: self.free_frequency(f, curr_time) diff = abs(tsys.center_frequency - frequency) if diff > self.input_rate/2: #print '%f request for frequency %d tgid %d failed, offset %d exceeds maximum %d' % (curr_time, frequency, tgid, diff, self.input_rate/2) continue update = True if frequency in self.working_frequencies: tgids = self.working_frequencies[frequency]['tgids'] if tgid in tgids: if tgids[tgid]['tdma_slot'] == tdma_slot: update = False else: print '%f slot switch %s was %s tgid %d frequency %d' % (curr_time, tdma_slot, tgids[tgid]['tdma_slot'], tgid, frequency) worker = self.working_frequencies[frequency]['worker'] else: #active_tdma_slots = [tgids[tg]['tdma_slot'] for tg in tgids] print '%f new tgid %d slot %s arriving on already active frequency %d' % (curr_time, tgid, tdma_slot, frequency) worker = self.working_frequencies[frequency]['worker'] else: worker = self.find_available_worker() if worker is None: print '*** error, no free demodulators, freq %d tgid %d' % (frequency, tgid) continue self.working_frequencies[frequency] = {'tgids' : {}, 'worker': worker} worker['demod'].set_relative_frequency(tsys.center_frequency - frequency) print '%f starting worker frequency %d tg %d slot %s' % (curr_time, frequency, tgid, tdma_slot) self.working_frequencies[frequency]['tgids'][tgid] = {'updated': curr_time, 'tdma_slot': tdma_slot} if not update: continue filename = 'tgid-%d-%f.wav' % (tgid, curr_time) print '%f update frequency %d tg %d slot %s file %s' % (curr_time, frequency, tgid, tdma_slot, filename) # set demod speed, decoder slot, output file name demod = worker['demod'] decoder = worker['decoder'] symbol_rate = 4800 if tdma_slot is None: index = 0 else: index = tdma_slot symbol_rate = 6000 xorhash = '%x%x%x' % (self.current_nac, tsys.ns_syid, tsys.ns_wacn) if xorhash not in self.xor_cache: self.xor_cache[xorhash] = lfsr.p25p2_lfsr(self.current_nac, tsys.ns_syid, tsys.ns_wacn).xor_chars decoder.set_xormask(self.xor_cache[xorhash], xorhash, index=index) demod.set_omega(symbol_rate) decoder.set_output(filename, index=index) # garbage collection if self.last_garbage_collect + 1 > curr_time: return self.last_garbage_collect = curr_time gc_frequencies = [] gc_tgids = [] for frequency in self.working_frequencies: tgids = self.working_frequencies[frequency]['tgids'] inactive_tgids = [[frequency, tgid] for tgid in tgids if tgids[tgid]['updated'] + self.TGID_HOLD_TIME < curr_time] if len(inactive_tgids) == len(tgids): gc_frequencies += [frequency] gc_tgids += inactive_tgids for frequency, tgid in gc_tgids: # expire talkgroups self.free_talkgroup(frequency, tgid, curr_time) for frequency in gc_frequencies: # expire working frequencies self.free_frequency(frequency, curr_time)
def main(): parser = OptionParser() parser.add_option("-v", "--verbose", action="store_true", default=False) parser.add_option("-i", "--input-file", type="string", default=None, help="input file name") parser.add_option("-n", "--nac", type="int", default=0, help="NAC") parser.add_option("-s", "--sysid", type="int", default=0, help="sysid") parser.add_option("-w", "--wacn", type="int", default=0, help="WACN") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) file = options.input_file my_isch = isch.p25p2_isch() my_duid = duid.p25p2_duid() my_lfsr = lfsr.p25p2_lfsr(options.nac, options.sysid, options.wacn) #print 'nac: %d' % options.nac d = open(file).read() symbols = [] for c in d: symbols.append(ord(c)) sync0= bits_to_dibits(mk_array(0x575d57f7ff,40)) sync_start = find_sym(sync0, symbols) assert sync_start > 0 # unable to locate any sync sequence superframe = -1 for i in xrange(sync_start, sync_start + (180*32), 180): chn, loc, fr, cnt = my_isch.decode_isch ( symbols [ i : i + 20 ]) if chn == 0 and loc == 0: superframe = i break assert superframe > 0 # unable to locate start of superframe errors = 0 for i in xrange(superframe,len(symbols)-SUPERFRAME_LEN,SUPERFRAME_LEN): syms1 = symbols[i + 10: i + SUPERFRAME_LEN + 10] syms2 = np.array(syms1) ^ my_lfsr.xorsyms for j in xrange(12): if options.verbose: print '%s superframe %d timeslot %d %s' % ('=' * 20, i, j, '=' * 20) chn, loc, fr, cnt = my_isch.decode_isch ( symbols [ i + (j*180) : i + (j*180) + 20 ]) if chn == -1: if options.verbose: print 'unknown isch codeword at %d' % (i + (j*180)) errors += 1 elif chn == -2: if options.verbose: print 'sync isch codeword found at %d' % (i + (j*180)) errors = 0 else: if options.verbose: print "channel %d loc %d fr %d count %d" % (chn, loc, fr, cnt) errors = 0 burst = syms1 [ (j*180) : (j*180) + 180 ] burst_d= syms2 [ (j*180) : (j*180) + 180 ] btype = my_duid.decode_duid(burst) if options.verbose: print 'burst at %d type %s' % (i + (j*180), btype) if btype == '2v' or btype == '4v': process_v(burst_d, btype) elif not btype.startswith('unknown'): maybe_sync = burst[79:79+21] if btype.endswith(' w'): # scrambled burst = burst_d # process_oemi(burst, btype) if errors > 6: if options.verbose: print "too many successive errors, exiting at i=%d" % (i) break