Houston, we have a trunk.
[debian/gnuradio] / gnuradio-core / src / python / gnuradio / blksimpl / gmsk2_pkt.py
1 #
2 # Copyright 2005,2006 Free Software Foundation, Inc.
3
4 # This file is part of GNU Radio
5
6 # GNU Radio 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 2, or (at your option)
9 # any later version.
10
11 # GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to
18 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 # Boston, MA 02111-1307, USA.
20
21
22 from math import pi
23 import Numeric
24
25 from gnuradio import gr, packet_utils
26 import gnuradio.gr.gr_threading as _threading
27 import gmsk2
28
29
30 def _deprecation_warning(old_name, new_name):
31     print '#'
32     print '#  Warning: %s is deprecated and will be removed soon.' % (old_name,)
33     print '#           Please use the modulation independent block, %s.' % (new_name,)
34     print "#"
35
36
37 # /////////////////////////////////////////////////////////////////////////////
38 #                   GMSK mod/demod with packets as i/o
39 # /////////////////////////////////////////////////////////////////////////////
40
41 class gmsk2_mod_pkts(gr.hier_block):
42     """
43     GSM modulator that is a GNU Radio source.
44
45     Send packets by calling send_pkt
46     """
47     def __init__(self, fg, access_code=None, msgq_limit=2, pad_for_usrp=True, *args, **kwargs):
48         """
49         Hierarchical block for Gaussian Minimum Shift Key (GMSK) modulation.
50
51         Packets to be sent are enqueued by calling send_pkt.
52         The output is the complex modulated signal at baseband.
53
54         @param fg: flow graph
55         @type fg: flow graph
56         @param access_code: AKA sync vector
57         @type access_code: string of 1's and 0's between 1 and 64 long
58         @param msgq_limit: maximum number of messages in message queue
59         @type msgq_limit: int
60         @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
61
62         See gmsk_mod for remaining parameters
63         """
64         _deprecation_warning('gmsk2_mod_pkts', 'mod_pkts')
65         
66         self.pad_for_usrp = pad_for_usrp
67         if access_code is None:
68             access_code = packet_utils.default_access_code
69         if not packet_utils.is_1_0_string(access_code):
70             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
71         self._access_code = access_code
72
73         # accepts messages from the outside world
74         self.pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
75         self.gmsk_mod = gmsk2.gmsk2_mod(fg, *args, **kwargs)
76         fg.connect(self.pkt_input, self.gmsk_mod)
77         gr.hier_block.__init__(self, fg, None, self.gmsk_mod)
78
79     def send_pkt(self, payload='', eof=False):
80         """
81         Send the payload.
82
83         @param payload: data to send
84         @type payload: string
85         """
86         if eof:
87             msg = gr.message(1) # tell self.pkt_input we're not sending any more packets
88         else:
89             # print "original_payload =", string_to_hex_list(payload)
90             pkt = packet_utils.make_packet(payload,
91                                            self.gmsk_mod.samples_per_baud(),
92                                            self.gmsk_mod.bits_per_baud(),
93                                            self._access_code,
94                                            self.pad_for_usrp)
95             #print "pkt =", string_to_hex_list(pkt)
96             msg = gr.message_from_string(pkt)
97         self.pkt_input.msgq().insert_tail(msg)
98
99
100
101 class gmsk2_demod_pkts(gr.hier_block):
102     """
103     GSM demodulator that is a GNU Radio sink.
104
105     The input is complex baseband.  When packets are demodulated, they are passed to the
106     app via the callback.
107     """
108
109     def __init__(self, fg, access_code=None, callback=None, threshold=-1, *args, **kwargs):
110         """
111         Hierarchical block for Gaussian Minimum Shift Key (GMSK)
112         demodulation.
113
114         The input is the complex modulated signal at baseband.
115         Demodulated packets are sent to the handler.
116
117         @param fg: flow graph
118         @type fg: flow graph
119         @param access_code: AKA sync vector
120         @type access_code: string of 1's and 0's
121         @param callback:  function of two args: ok, payload
122         @type callback: ok: bool; payload: string
123         @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
124         @type threshold: int
125
126         See gmsk_demod for remaining parameters.
127         """
128
129         _deprecation_warning('gmsk2_demod_pkts', 'demod_pkts')
130
131         if access_code is None:
132             access_code = packet_utils.default_access_code
133         if not packet_utils.is_1_0_string(access_code):
134             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
135         self._access_code = access_code
136
137         if threshold == -1:
138             threshold = 12              # FIXME raise exception
139
140         self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY
141         self.gmsk_demod = gmsk2.gmsk2_demod(fg, *args, **kwargs)
142         self.correlator = gr.correlate_access_code_bb(access_code, threshold)
143
144         self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
145         fg.connect(self.gmsk_demod, self.correlator, self.framer_sink)
146         
147         gr.hier_block.__init__(self, fg, self.gmsk_demod, None)
148         self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
149
150     def carrier_sensed(self):
151         """
152         Return True if we detect carrier.
153         """
154         return False        # FIXME
155
156
157 class _queue_watcher_thread(_threading.Thread):
158     def __init__(self, rcvd_pktq, callback):
159         _threading.Thread.__init__(self)
160         self.setDaemon(1)
161         self.rcvd_pktq = rcvd_pktq
162         self.callback = callback
163         self.keep_running = True
164         self.start()
165
166     #def stop(self):
167     #    self.keep_running = False
168         
169     def run(self):
170         while self.keep_running:
171             msg = self.rcvd_pktq.delete_head()
172             ok, payload = packet_utils.unmake_packet(msg.to_string())
173             if self.callback:
174                 self.callback(ok, payload)