blob: ca3c423d40fd25529499a911e0e70035b714def4 [file] [log] [blame]
piotr6b78abc2014-07-08 23:29:13 +02001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
piotrd8506d62014-07-20 23:52:57 +02004# Copyright 2014 Piotr Krysik pkrysik@elka.pw.edu.pl
piotr6b78abc2014-07-08 23:29:13 +02005#
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)
piotrd8506d62014-07-20 23:52:57 +020057 power_bl_mov_avg = uniform_filter1d(abs(correlation_bl)**2,self.L+1,mode='constant',axis=0)
piotr6b78abc2014-07-08 23:29:13 +020058
piotrd8506d62014-07-20 23:52:57 +020059 print "correlation_bl.argmax()",argmax(abs(correlation_bl))
60 print "power_bl_mov_avg.argmax()",(power_bl_mov_avg).argmax()
61 print 'unravel_index(correlation_bl.argmax(), correlation_bl.shape)',unravel_index(argmax(abs(correlation_bl)), correlation_bl.shape)
piotr6b78abc2014-07-08 23:29:13 +020062 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)
piotrd8506d62014-07-20 23:52:57 +020063 (r_corrmax, c_corrmax)=unravel_index(argmax(abs(correlation_bl)), correlation_bl.shape)
64 (r_powmax, c_powmax)=unravel_index(power_bl_mov_avg.argmax(), power_bl_mov_avg.shape)
65
piotr6b78abc2014-07-08 23:29:13 +020066# correlation = zeros(shape(sch_burst))
67# correlation = correlate(sch_burst, self.sync_seq_msk_interp,'same')/len(self.sync_seq_msk)
68# print "pozycja maksimum",argmax(abs(correlation))
piotrd8506d62014-07-20 23:52:57 +020069# plot(abs(hstack(correlation_bl))*1000)
70## hold(True)
71## plot(abs(sch_burst)*500)
72## print shape(range(0,len(sch_burst),self.OSR))
73## print shape(correlation_bl[:,0])
74# for ii in range(0,self.OSR):
75# if ii == c_powmax:
76# plot(range(ii,len(correlation_bl[:,0])*self.OSR,self.OSR),power_bl_mov_avg[:,ii]*5e6,'g.')
77# else:
78# plot(range(ii,len(correlation_bl[:,0])*self.OSR,self.OSR),power_bl_mov_avg[:,ii]*5e6,'r.')
79# show()
80# figure()
81 print 'r_powmax: ',r_powmax
82# plot(abs(correlation_bl[range(r_powmax-(self.L+1)/2+1,r_powmax+(self.L+1)/2+1), c_powmax]),'g')
piotr6b78abc2014-07-08 23:29:13 +020083# hold(True)
piotrd8506d62014-07-20 23:52:57 +020084# plot(abs(correlation_bl[range(r_corrmax-(self.L+1)/2+1,r_corrmax+(self.L+1)/2+1), c_corrmax]),'r')
85# show()
86
piotr6b78abc2014-07-08 23:29:13 +020087 def receive(self, input_corr, chan_imp_resp):
88 pass
89
90class sch_detector(gr.sync_block):
91 """
92 docstring for block sch_detector
93 """
94 def __init__(self, OSR):
95 gr.sync_block.__init__(self,
96 name="sch_detector",
97 in_sig=[complex64],
98 out_sig=[complex64])
99 self.OSR = OSR
100 self.states = {"waiting_for_fcch_tag":1, "reaching_sch_burst":2, "sch_at_input_buffer":3}
101 self.state = self.states["waiting_for_fcch_tag"]
102 self.sch_offset = -100 #-100 - just some invalid value of sch burst position in the stream
103 self.burst_size = int(round(156.25*self.OSR))
104 self.guard_period = int(round(8.25*self.OSR))
105 self.block_size = self.burst_size + self.guard_period
106 self.set_history(self.block_size)
107 self.set_output_multiple(self.guard_period)
108 self.sch_receiver = sch_receiver(OSR)
109
110 def work(self, input_items, output_items):
111 in0 = input_items[0]
112 out = output_items[0]
113 to_consume = len(in0)-self.history()
114
115 if self.state == self.states["waiting_for_fcch_tag"]:
116 fcch_tags = []
117
118 start = self.nitems_written(0)
119 stop = start + len(in0)
120 key = pmt.string_to_symbol("fcch")
121 fcch_tags = self.get_tags_in_range(0, start, stop, key)
122 if fcch_tags:
123 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,
124 #8.25 is arbitrary safety margin in order to avoid cutting boundary of SCH burst
125 self.state = self.states["reaching_sch_burst"]
126
127 elif self.state == self.states["reaching_sch_burst"]:
128 samples_left = self.sch_offset-self.nitems_written(0)
129 if samples_left <= len(in0)-self.history():
130 to_consume = samples_left
131 self.state = self.states["sch_at_input_buffer"]
132
133 elif self.state == self.states["sch_at_input_buffer"]:
134 offset = self.nitems_written(0)
135 key = pmt.string_to_symbol("sch")
136 value = pmt.from_double(0)
137 self.add_item_tag(0,offset, key, value)
138 self.state = self.states["waiting_for_fcch_tag"]
139 self.sch_receiver.get_chan_imp_resp(in0[0:self.block_size+self.guard_period])
140# plot(unwrap(angle(in0[0:2*self.block_size])))
141# show()
142
143 out[:] = in0[self.history()-1:]
144 return to_consume
piotrd8506d62014-07-20 23:52:57 +0200145
146 def get_OSR(self):
147 return self.OSR
148
149 def set_OSR(self, OSR):
150 self.OSR = OSR
151 self.burst_size = int(round(156.25*self.OSR))
152 self.guard_period = int(round(8.25*self.OSR))
153 self.block_size = self.burst_size + self.guard_period
154 self.set_history(self.block_size)
155 self.sch_receiver = sch_receiver(OSR)
piotr6b78abc2014-07-08 23:29:13 +0200156