Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / python / gnuradio / blks2impl / pkt.py
1 #
2 # Copyright 2005, 2006, 2007 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 3, 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., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
20
21
22 from math import pi
23 from gnuradio import gr, packet_utils
24 import gnuradio.gr.gr_threading as _threading
25
26
27 # /////////////////////////////////////////////////////////////////////////////
28 #                   mod/demod with packets as i/o
29 # /////////////////////////////////////////////////////////////////////////////
30
31 class mod_pkts(gr.hier_block2):
32     """
33     Wrap an arbitrary digital modulator in our packet handling framework.
34
35     Send packets by calling send_pkt
36     """
37     def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False):
38         """
39         Hierarchical block for sending packets
40
41         Packets to be sent are enqueued by calling send_pkt.
42         The output is the complex modulated signal at baseband.
43
44         @param modulator: instance of modulator class (gr_block or hier_block2)
45         @type modulator: complex baseband out
46         @param access_code: AKA sync vector
47         @type access_code: string of 1's and 0's between 1 and 64 long
48         @param msgq_limit: maximum number of messages in message queue
49         @type msgq_limit: int
50         @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
51         @param use_whitener_offset: If true, start of whitener XOR string is incremented each packet
52         
53         See gmsk_mod for remaining parameters
54         """
55
56         gr.hier_block2.__init__(self, "mod_pkts",
57                                 gr.io_signature(0, 0, 0),                    # Input signature
58                                 gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
59
60         self._modulator = modulator
61         self._pad_for_usrp = pad_for_usrp
62         self._use_whitener_offset = use_whitener_offset
63         self._whitener_offset = 0
64         
65         if access_code is None:
66             access_code = packet_utils.default_access_code
67         if not packet_utils.is_1_0_string(access_code):
68             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
69         self._access_code = access_code
70
71         # accepts messages from the outside world
72         self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
73         self.connect(self._pkt_input, self._modulator, self)
74
75     def send_pkt(self, payload='', eof=False):
76         """
77         Send the payload.
78
79         @param payload: data to send
80         @type payload: string
81         """
82         if eof:
83             msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
84         else:
85             # print "original_payload =", string_to_hex_list(payload)
86             pkt = packet_utils.make_packet(payload,
87                                            self._modulator.samples_per_symbol(),
88                                            self._modulator.bits_per_symbol(),
89                                            self._access_code,
90                                            self._pad_for_usrp,
91                                            self._whitener_offset)
92             #print "pkt =", string_to_hex_list(pkt)
93             msg = gr.message_from_string(pkt)
94             if self._use_whitener_offset is True:
95                 self._whitener_offset = (self._whitener_offset + 1) % 16
96                 
97         self._pkt_input.msgq().insert_tail(msg)
98
99
100
101 class demod_pkts(gr.hier_block2):
102     """
103     Wrap an arbitrary digital demodulator in our packet handling framework.
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, demodulator, access_code=None, callback=None, threshold=-1):
110         """
111         Hierarchical block for demodulating and deframing packets.
112
113         The input is the complex modulated signal at baseband.
114         Demodulated packets are sent to the handler.
115
116         @param demodulator: instance of demodulator class (gr_block or hier_block2)
117         @type demodulator: complex baseband in
118         @param access_code: AKA sync vector
119         @type access_code: string of 1's and 0's
120         @param callback:  function of two args: ok, payload
121         @type callback: ok: bool; payload: string
122         @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
123         @type threshold: int
124         """
125
126         gr.hier_block2.__init__(self, "demod_pkts",
127                                 gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
128                                 gr.io_signature(0, 0, 0))                    # Output signature
129
130         self._demodulator = demodulator
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.correlator = gr.correlate_access_code_bb(access_code, threshold)
142
143         self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
144         self.connect(self, self._demodulator, self.correlator, self.framer_sink)
145         
146         self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
147
148
149 class _queue_watcher_thread(_threading.Thread):
150     def __init__(self, rcvd_pktq, callback):
151         _threading.Thread.__init__(self)
152         self.setDaemon(1)
153         self.rcvd_pktq = rcvd_pktq
154         self.callback = callback
155         self.keep_running = True
156         self.start()
157
158
159     def run(self):
160         while self.keep_running:
161             msg = self.rcvd_pktq.delete_head()
162             ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1()))
163             if self.callback:
164                 self.callback(ok, payload)