Fixed base class name.
[debian/gnuradio] / gnuradio-core / src / python / gnuradio / blksimpl2 / 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):
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_block)
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         """
52
53         gr.hier_block2.__init__(self, "mod_pkts",
54                                 gr.io_signature(0,0,0), # Input signature
55                                 gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
56
57         self._modulator = modulator
58         self._pad_for_usrp = pad_for_usrp
59
60         if access_code is None:
61             access_code = packet_utils.default_access_code
62         if not packet_utils.is_1_0_string(access_code):
63             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
64         self._access_code = access_code
65
66         # accepts messages from the outside world
67         self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
68         self.connect(self._pkt_input, self._modulator, self)
69
70     def send_pkt(self, payload='', eof=False):
71         """
72         Send the payload.
73
74         @param payload: data to send
75         @type payload: string
76         """
77         if eof:
78             msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
79         else:
80             # print "original_payload =", string_to_hex_list(payload)
81             pkt = packet_utils.make_packet(payload,
82                                            self._modulator.samples_per_symbol(),
83                                            self._modulator.bits_per_symbol(),
84                                            self._access_code,
85                                            self._pad_for_usrp)
86             #print "pkt =", string_to_hex_list(pkt)
87             msg = gr.message_from_string(pkt)
88         self._pkt_input.msgq().insert_tail(msg)
89
90
91
92 class demod_pkts(gr.hier_block2):
93     """
94     Wrap an arbitrary digital demodulator in our packet handling framework.
95
96     The input is complex baseband.  When packets are demodulated, they are passed to the
97     app via the callback.
98     """
99
100     def __init__(self, demodulator, access_code=None, callback=None, threshold=-1):
101         """
102         Hierarchical block for demodulating and deframing packets.
103
104         The input is the complex modulated signal at baseband.
105         Demodulated packets are sent to the handler.
106
107         @param demodulator: instance of demodulator class (gr_block or hier_block)
108         @type demodulator: complex baseband in
109         @param access_code: AKA sync vector
110         @type access_code: string of 1's and 0's
111         @param callback:  function of two args: ok, payload
112         @type callback: ok: bool; payload: string
113         @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
114         @type threshold: int
115         """
116
117         gr.hier_block2.__init__(self, "demod_pkts",
118                                 gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
119                                 gr.io_signature(0,0,0)) # Output signature
120                                 
121         self._demodulator = demodulator
122         if access_code is None:
123             access_code = packet_utils.default_access_code
124         if not packet_utils.is_1_0_string(access_code):
125             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
126         self._access_code = access_code
127
128         if threshold == -1:
129             threshold = 12              # FIXME raise exception
130
131         self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY
132
133         self._correlator = gr.correlate_access_code_bb(access_code, threshold)
134         self._framer_sink = gr.framer_sink_1(self._rcvd_pktq)
135         self.connect(self, self._demodulator, self._correlator, self._framer_sink)
136
137         self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
138
139
140 class _queue_watcher_thread(_threading.Thread):
141     def __init__(self, rcvd_pktq, callback):
142         _threading.Thread.__init__(self)
143         self.setDaemon(1)
144         self.rcvd_pktq = rcvd_pktq
145         self.callback = callback
146         self.keep_running = True
147         self.start()
148
149
150     def run(self):
151         while self.keep_running:
152             msg = self.rcvd_pktq.delete_head()
153             ok, payload = packet_utils.unmake_packet(msg.to_string())
154             if self.callback:
155                 self.callback(ok, payload)