blob: d80d03274f239599121560f7fa57123b87449c58 [file] [log] [blame]
piotr6b78abc2014-07-08 23:29:13 +02001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright 2014 <+YOU OR YOUR COMPANY+>.
5#
6# This is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3, or (at your option)
9# any later version.
10#
11# This software is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this software; see the file COPYING. If not, write to
18# the Free Software Foundation, Inc., 51 Franklin Street,
19# Boston, MA 02110-1301, USA.
20#
21
22from numpy import *
23from pylab import *
24from gnuradio import gr
25import pmt
26from scipy.ndimage.filters import uniform_filter1d
27
28class sch_receiver():
29 """
30 docstring for class sch_reciever
31 """
32 def __init__(self, OSR):
33 self.sync_seq = array([1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0,
34 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
35 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1,
36 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1])
37 self.OSR = OSR
38 sync_seq_msk_tmp = self.msk_mod(self.sync_seq, -1j)
39 self.sync_seq_msk = sync_seq_msk_tmp[5:59]
40 self.sync_seq_msk_interp = zeros(self.OSR*len(self.sync_seq_msk), dtype=np.complex64)
41 self.sync_seq_msk_interp[::OSR] = self.sync_seq_msk
42 self.L = 5
43
44 def msk_mod(self, x, start_point):
45 x_nrz = 2*x-1
46 x_diffenc = x_nrz[1:]*x_nrz[0:-1]
47 mod_tmp = concatenate((array([start_point]),1j*x_diffenc))
48 return cumprod(mod_tmp)
49
50 def get_chan_imp_resp(self, sch_burst):
51 sch_burst_bl = resize(array(sch_burst), (int(len(sch_burst)/self.OSR),self.OSR))
52 correlation_bl = zeros(shape(sch_burst_bl), dtype=np.complex64)
53 for ii in xrange(0,self.OSR):
54 correlation_bl[:,ii]=correlate(sch_burst_bl[:,ii],self.sync_seq_msk,'same')
55
56 correlation_bl = correlation_bl/len(self.sync_seq_msk)
57 power_bl_mov_avg = uniform_filter1d(abs(correlation_bl)**2,5,mode='constant',axis=0)
58
59 print "correlation_bl.argmax()",argmax(abs(hstack(correlation_bl)))
60 print "power_bl_mov_avg.argmax()",hstack(power_bl_mov_avg).argmax()
61 print 'unravel_index(correlation_bl.argmax(), correlation_bl.shape)',unravel_index(correlation_bl.argmax(), correlation_bl.shape)
62 print 'unravel_index(power_bl_mov_avg.argmax(), power_bl_mov_avg.shape)',unravel_index(power_bl_mov_avg.argmax(), power_bl_mov_avg.shape)
63# correlation = zeros(shape(sch_burst))
64# correlation = correlate(sch_burst, self.sync_seq_msk_interp,'same')/len(self.sync_seq_msk)
65# print "pozycja maksimum",argmax(abs(correlation))
66 plot(abs(hstack(correlation_bl))*1000)
67# hold(True)
68# plot(abs(sch_burst)*500)
69# print shape(range(0,len(sch_burst),self.OSR))
70# print shape(correlation_bl[:,0])
71 for ii in range(0,self.OSR):
72 plot(range(ii,len(correlation_bl[:,0])*self.OSR,self.OSR),power_bl_mov_avg[:,ii]*5e6,'r.')
73 show()
74 def receive(self, input_corr, chan_imp_resp):
75 pass
76
77class sch_detector(gr.sync_block):
78 """
79 docstring for block sch_detector
80 """
81 def __init__(self, OSR):
82 gr.sync_block.__init__(self,
83 name="sch_detector",
84 in_sig=[complex64],
85 out_sig=[complex64])
86 self.OSR = OSR
87 self.states = {"waiting_for_fcch_tag":1, "reaching_sch_burst":2, "sch_at_input_buffer":3}
88 self.state = self.states["waiting_for_fcch_tag"]
89 self.sch_offset = -100 #-100 - just some invalid value of sch burst position in the stream
90 self.burst_size = int(round(156.25*self.OSR))
91 self.guard_period = int(round(8.25*self.OSR))
92 self.block_size = self.burst_size + self.guard_period
93 self.set_history(self.block_size)
94 self.set_output_multiple(self.guard_period)
95 self.sch_receiver = sch_receiver(OSR)
96
97 def work(self, input_items, output_items):
98 in0 = input_items[0]
99 out = output_items[0]
100 to_consume = len(in0)-self.history()
101
102 if self.state == self.states["waiting_for_fcch_tag"]:
103 fcch_tags = []
104
105 start = self.nitems_written(0)
106 stop = start + len(in0)
107 key = pmt.string_to_symbol("fcch")
108 fcch_tags = self.get_tags_in_range(0, start, stop, key)
109 if fcch_tags:
110 self.sch_offset = fcch_tags[0].offset + int(round(8*self.burst_size+0*self.guard_period)) #156.25 is number of GMSK symbols per timeslot,
111 #8.25 is arbitrary safety margin in order to avoid cutting boundary of SCH burst
112 self.state = self.states["reaching_sch_burst"]
113
114 elif self.state == self.states["reaching_sch_burst"]:
115 samples_left = self.sch_offset-self.nitems_written(0)
116 if samples_left <= len(in0)-self.history():
117 to_consume = samples_left
118 self.state = self.states["sch_at_input_buffer"]
119
120 elif self.state == self.states["sch_at_input_buffer"]:
121 offset = self.nitems_written(0)
122 key = pmt.string_to_symbol("sch")
123 value = pmt.from_double(0)
124 self.add_item_tag(0,offset, key, value)
125 self.state = self.states["waiting_for_fcch_tag"]
126 self.sch_receiver.get_chan_imp_resp(in0[0:self.block_size+self.guard_period])
127# plot(unwrap(angle(in0[0:2*self.block_size])))
128# show()
129
130 out[:] = in0[self.history()-1:]
131 return to_consume
132