2 # Copyright 2005, 2006, 2007 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 3, 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.
23 from gnuradio import gr, packet_utils
24 import gnuradio.gr.gr_threading as _threading
27 # /////////////////////////////////////////////////////////////////////////////
28 # mod/demod with packets as i/o
29 # /////////////////////////////////////////////////////////////////////////////
31 class mod_pkts(gr.hier_block2):
33 Wrap an arbitrary digital modulator in our packet handling framework.
35 Send packets by calling send_pkt
37 def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False):
39 Hierarchical block for sending packets
41 Packets to be sent are enqueued by calling send_pkt.
42 The output is the complex modulated signal at baseband.
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
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
53 See gmsk_mod for remaining parameters
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
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
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
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)
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_block2):
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, 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 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)
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
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
138 threshold = 12 # FIXME raise exception
140 self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY
141 self.correlator = gr.correlate_access_code_bb(access_code, threshold)
143 self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
144 self.connect(self, self._demodulator, self.correlator, self.framer_sink)
146 self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
149 class _queue_watcher_thread(_threading.Thread):
150 def __init__(self, rcvd_pktq, callback):
151 _threading.Thread.__init__(self)
153 self.rcvd_pktq = rcvd_pktq
154 self.callback = callback
155 self.keep_running = True
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()))
164 self.callback(ok, payload)