2 # Copyright 2005,2006 Free Software Foundation, Inc.
4 # This file is part of GNU Radio
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)
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.
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.
25 from gnuradio import gr, packet_utils
26 import gnuradio.gr.gr_threading as _threading
29 # /////////////////////////////////////////////////////////////////////////////
30 # mod/demod with packets as i/o
31 # /////////////////////////////////////////////////////////////////////////////
33 class mod_pkts(gr.hier_block2):
35 Wrap an arbitrary digital modulator in our packet handling framework.
37 Send packets by calling send_pkt
39 def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True):
41 Hierarchical block for sending packets
43 Packets to be sent are enqueued by calling send_pkt.
44 The output is the complex modulated signal at baseband.
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
52 @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
55 gr.hier_block2.__init__(self, "mod_pkts",
56 gr.io_signature(0,0,0), # Input signature
57 gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
59 self._modulator = modulator
60 self._pad_for_usrp = pad_for_usrp
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
68 # accepts messages from the outside world
69 self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
70 self.define_component("packet_source", self._pkt_input)
71 self.define_component("modulator", self._modulator)
73 self.connect("packet_source", 0, "modulator", 0)
74 self.connect("modulator", 0, "self", 0)
76 def send_pkt(self, payload='', eof=False):
80 @param payload: data to send
84 msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
86 # print "original_payload =", string_to_hex_list(payload)
87 pkt = packet_utils.make_packet(payload,
88 self._modulator.samples_per_symbol(),
89 self._modulator.bits_per_symbol(),
92 #print "pkt =", string_to_hex_list(pkt)
93 msg = gr.message_from_string(pkt)
94 self._pkt_input.msgq().insert_tail(msg)
98 class demod_pkts(gr.hier_block2):
100 Wrap an arbitrary digital demodulator in our packet handling framework.
102 The input is complex baseband. When packets are demodulated, they are passed to the
103 app via the callback.
106 def __init__(self, demodulator, access_code=None, callback=None, threshold=-1):
108 Hierarchical block for demodulating and deframing packets.
110 The input is the complex modulated signal at baseband.
111 Demodulated packets are sent to the handler.
113 @param demodulator: instance of demodulator class (gr_block or hier_block)
114 @type demodulator: complex baseband in
115 @param access_code: AKA sync vector
116 @type access_code: string of 1's and 0's
117 @param callback: function of two args: ok, payload
118 @type callback: ok: bool; payload: string
119 @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
123 gr.hier_block2.__init__(self, "demod_pkts",
124 gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
125 gr.io_signature(0,0,0)) # Output signature
127 self._demodulator = demodulator
128 if access_code is None:
129 access_code = packet_utils.default_access_code
130 if not packet_utils.is_1_0_string(access_code):
131 raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
132 self._access_code = access_code
135 threshold = 12 # FIXME raise exception
137 self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY
139 self.define_component("demodulator", self._demodulator)
140 self.define_component("correlator", gr.correlate_access_code_bb(access_code, threshold))
141 self.define_component("framer_sink", gr.framer_sink_1(self._rcvd_pktq))
143 self.connect("self", 0, "demodulator",0)
144 self.connect("demodulator", 0, "correlator", 0)
145 self.connect("correlator", 0, "framer_sink", 0)
147 self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
150 class _queue_watcher_thread(_threading.Thread):
151 def __init__(self, rcvd_pktq, callback):
152 _threading.Thread.__init__(self)
154 self.rcvd_pktq = rcvd_pktq
155 self.callback = callback
156 self.keep_running = True
161 while self.keep_running:
162 msg = self.rcvd_pktq.delete_head()
163 ok, payload = packet_utils.unmake_packet(msg.to_string())
165 self.callback(ok, payload)