Updated license from GPL version 2 or later to GPL version 3 or later.
[debian/gnuradio] / gnuradio-core / src / python / gnuradio / blksimpl / 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 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_block):
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, fg, 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 fg: flow graph
45         @type fg: flow graph
46         @param modulator: instance of modulator class (gr_block or hier_block)
47         @type modulator: complex baseband out
48         @param access_code: AKA sync vector
49         @type access_code: string of 1's and 0's between 1 and 64 long
50         @param msgq_limit: maximum number of messages in message queue
51         @type msgq_limit: int
52         @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
53         @param use_whitener_offset: If true, start of whitener XOR string is incremented each packet
54         
55         See gmsk_mod for remaining parameters
56         """
57         self._modulator = modulator
58         self._pad_for_usrp = pad_for_usrp
59         self._use_whitener_offset = use_whitener_offset
60         self._whitener_offset = 0
61         
62         if access_code is None:
63             access_code = packet_utils.default_access_code
64         if not packet_utils.is_1_0_string(access_code):
65             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
66         self._access_code = access_code
67
68         # accepts messages from the outside world
69         self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
70         fg.connect(self._pkt_input, self._modulator)
71         gr.hier_block.__init__(self, fg, None, self._modulator)
72
73     def send_pkt(self, payload='', eof=False):
74         """
75         Send the payload.
76
77         @param payload: data to send
78         @type payload: string
79         """
80         if eof:
81             msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
82         else:
83             # print "original_payload =", string_to_hex_list(payload)
84             pkt = packet_utils.make_packet(payload,
85                                            self._modulator.samples_per_symbol(),
86                                            self._modulator.bits_per_symbol(),
87                                            self._access_code,
88                                            self._pad_for_usrp,
89                                            self._whitener_offset)
90             #print "pkt =", string_to_hex_list(pkt)
91             msg = gr.message_from_string(pkt)
92             if self._use_whitener_offset is True:
93                 self._whitener_offset = (self._whitener_offset + 1) % 16
94                 
95         self._pkt_input.msgq().insert_tail(msg)
96
97
98
99 class demod_pkts(gr.hier_block):
100     """
101     Wrap an arbitrary digital demodulator in our packet handling framework.
102
103     The input is complex baseband.  When packets are demodulated, they are passed to the
104     app via the callback.
105     """
106
107     def __init__(self, fg, demodulator, access_code=None, callback=None, threshold=-1):
108         """
109         Hierarchical block for demodulating and deframing packets.
110
111         The input is the complex modulated signal at baseband.
112         Demodulated packets are sent to the handler.
113
114         @param fg: flow graph
115         @type fg: flow graph
116         @param demodulator: instance of demodulator class (gr_block or hier_block)
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         self._demodulator = demodulator
127         if access_code is None:
128             access_code = packet_utils.default_access_code
129         if not packet_utils.is_1_0_string(access_code):
130             raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
131         self._access_code = access_code
132
133         if threshold == -1:
134             threshold = 12              # FIXME raise exception
135
136         self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY
137         self.correlator = gr.correlate_access_code_bb(access_code, threshold)
138
139         self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
140         fg.connect(self._demodulator, self.correlator, self.framer_sink)
141         
142         gr.hier_block.__init__(self, fg, self._demodulator, None)
143         self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
144
145
146 class _queue_watcher_thread(_threading.Thread):
147     def __init__(self, rcvd_pktq, callback):
148         _threading.Thread.__init__(self)
149         self.setDaemon(1)
150         self.rcvd_pktq = rcvd_pktq
151         self.callback = callback
152         self.keep_running = True
153         self.start()
154
155
156     def run(self):
157         while self.keep_running:
158             msg = self.rcvd_pktq.delete_head()
159             ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1()))
160             if self.callback:
161                 self.callback(ok, payload)