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_block):
35 Wrap an arbitrary digital modulator in our packet handling framework.
37 Send packets by calling send_pkt
39 def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False):
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.
48 @param modulator: instance of modulator class (gr_block or hier_block)
49 @type modulator: complex baseband out
50 @param access_code: AKA sync vector
51 @type access_code: string of 1's and 0's between 1 and 64 long
52 @param msgq_limit: maximum number of messages in message queue
54 @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
55 @param use_whitener_offset: If true, start of whitener XOR string is incremented each packet
57 See gmsk_mod for remaining parameters
59 self._modulator = modulator
60 self._pad_for_usrp = pad_for_usrp
61 self._use_whitener_offset = use_whitener_offset
62 self._whitener_offset = 0
64 if access_code is None:
65 access_code = packet_utils.default_access_code
66 if not packet_utils.is_1_0_string(access_code):
67 raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
68 self._access_code = access_code
70 # accepts messages from the outside world
71 self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
72 fg.connect(self._pkt_input, self._modulator)
73 gr.hier_block.__init__(self, fg, None, self._modulator)
75 def send_pkt(self, payload='', eof=False):
79 @param payload: data to send
83 msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
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(),
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
97 self._pkt_input.msgq().insert_tail(msg)
101 class demod_pkts(gr.hier_block):
103 Wrap an arbitrary digital demodulator in our packet handling framework.
105 The input is complex baseband. When packets are demodulated, they are passed to the
106 app via the callback.
109 def __init__(self, fg, demodulator, access_code=None, callback=None, threshold=-1):
111 Hierarchical block for demodulating and deframing packets.
113 The input is the complex modulated signal at baseband.
114 Demodulated packets are sent to the handler.
116 @param fg: flow graph
118 @param demodulator: instance of demodulator class (gr_block or hier_block)
119 @type demodulator: complex baseband in
120 @param access_code: AKA sync vector
121 @type access_code: string of 1's and 0's
122 @param callback: function of two args: ok, payload
123 @type callback: ok: bool; payload: string
124 @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
128 self._demodulator = demodulator
129 if access_code is None:
130 access_code = packet_utils.default_access_code
131 if not packet_utils.is_1_0_string(access_code):
132 raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
133 self._access_code = access_code
136 threshold = 12 # FIXME raise exception
138 self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY
139 self.correlator = gr.correlate_access_code_bb(access_code, threshold)
141 self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
142 fg.connect(self._demodulator, self.correlator, self.framer_sink)
144 gr.hier_block.__init__(self, fg, self._demodulator, None)
145 self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
148 class _queue_watcher_thread(_threading.Thread):
149 def __init__(self, rcvd_pktq, callback):
150 _threading.Thread.__init__(self)
152 self.rcvd_pktq = rcvd_pktq
153 self.callback = callback
154 self.keep_running = True
159 while self.keep_running:
160 msg = self.rcvd_pktq.delete_head()
161 ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1()))
163 self.callback(ok, payload)