Revision c4e072e8

b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc
52 52
}
53 53

54 54
inline void
55
gr_framer_sink_1::enter_have_header(int payload_len)
55
gr_framer_sink_1::enter_have_header(int payload_len, int whitener_offset)
56 56
{
57 57
  if (VERBOSE)
58
    fprintf(stderr, "@ enter_have_header (payload_len = %d)\n", payload_len);
58
    fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", payload_len, whitener_offset);
59 59

60 60
  d_state = STATE_HAVE_HEADER;
61 61
  d_packetlen = payload_len;
62
  d_packet_whitener_offset = whitener_offset;
62 63
  d_packetlen_cnt = 0;
63 64
  d_packet_byte = 0;
64 65
  d_packet_byte_index = 0;
......
125 126

126 127
	  // we have a full header, check to see if it has been received properly
127 128
	  if (header_ok()){
128
	    int payload_len = header_payload_len();
129
	    if (payload_len <= MAX_PKT_LEN)		// reasonable?
130
	      enter_have_header(payload_len);		// yes.
131
	    else
132
	      enter_search();				// no.
129
	    int payload_len;
130
	    int payload_offset;
131
	    header_payload(&payload_len, &payload_offset);
132
	    enter_have_header(payload_len, payload_offset);
133 133
	  }
134 134
	  else
135 135
	    enter_search();				// no.
......
151 151
	  if (d_packetlen_cnt == d_packetlen){		// packet is filled
152 152

153 153
	    // build a message
154
	    gr_message_sptr msg = gr_make_message(0, 0, 0, d_packetlen_cnt);  	    
154
	    // NOTE: passing header field as arg1 is not scalable
155
	    gr_message_sptr msg = gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt);  	    
155 156
	    memcpy(msg->msg(), d_packet, d_packetlen_cnt);
156 157

157 158
	    d_target_queue->insert_tail(msg);		// send it
b/gnuradio-core/src/lib/general/gr_framer_sink_1.h
70 70
  unsigned char	     d_packet_byte;		// byte being assembled
71 71
  int		     d_packet_byte_index;	// which bit of d_packet_byte we're working on
72 72
  int 		     d_packetlen;		// length of packet
73
  int                d_packet_whitener_offset;  // offset into whitener string to use
73 74
  int		     d_packetlen_cnt;		// how many so far
74 75

75 76
 protected:
......
77 78

78 79
  void enter_search();
79 80
  void enter_have_sync();
80
  void enter_have_header(int payload_len);
81
  void enter_have_header(int payload_len, int whitener_offset);
81 82
  
82 83
  bool header_ok()
83 84
  {
......
85 86
    return ((d_header >> 16) ^ (d_header & 0xffff)) == 0;
86 87
  }
87 88

88
  int header_payload_len()
89
  void header_payload(int *len, int *offset)
89 90
  {
90 91
    // header consists of two 16-bit shorts in network byte order
91
    int t = (d_header >> 16) & 0xffff;
92
    return t;
92
    // payload length is lower 12 bits
93
    // whitener offset is upper 4 bits
94
    *len = (d_header >> 16) & 0x0fff;
95
    *offset = (d_header >> 28) & 0x000f;
93 96
  }
94 97

95 98
 public:
b/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py
36 36

37 37
    Send packets by calling send_pkt
38 38
    """
39
    def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True):
39
    def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False):
40 40
        """
41 41
	Hierarchical block for sending packets
42 42

......
52 52
        @param msgq_limit: maximum number of messages in message queue
53 53
        @type msgq_limit: int
54 54
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
55

55
        @param use_whitener_offset: If true, start of whitener XOR string is incremented each packet
56
        
56 57
        See gmsk_mod for remaining parameters
57 58
        """
58 59
        self._modulator = modulator
59 60
        self._pad_for_usrp = pad_for_usrp
60

61
        self._use_whitener_offset = use_whitener_offset
62
        self._whitener_offset = 0
63
        
61 64
        if access_code is None:
62 65
            access_code = packet_utils.default_access_code
63 66
        if not packet_utils.is_1_0_string(access_code):
......
84 87
                                           self._modulator.samples_per_symbol(),
85 88
                                           self._modulator.bits_per_symbol(),
86 89
                                           self._access_code,
87
                                           self._pad_for_usrp)
90
                                           self._pad_for_usrp,
91
                                           self._whitener_offset)
88 92
            #print "pkt =", string_to_hex_list(pkt)
89 93
            msg = gr.message_from_string(pkt)
94
            if self._use_whitener_offset is True:
95
                self._whitener_offset = (self._whitener_offset + 1) % 16
96
                
90 97
        self._pkt_input.msgq().insert_tail(msg)
91 98

92 99

......
151 158
    def run(self):
152 159
        while self.keep_running:
153 160
            msg = self.rcvd_pktq.delete_head()
154
            ok, payload = packet_utils.unmake_packet(msg.to_string())
161
            ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1()))
155 162
            if self.callback:
156 163
                self.callback(ok, payload)
b/gnuradio-core/src/python/gnuradio/packet_utils.py
86 86
    return map(lambda x: hex(ord(x)), s)
87 87

88 88

89
def whiten(s):
89
def whiten(s, o):
90 90
    sa = Numeric.fromstring(s, Numeric.UnsignedInt8)
91
    z = sa ^ random_mask_vec8[0:len(sa)]
91
    z = sa ^ random_mask_vec8[o:len(sa)+o]
92 92
    return z.tostring()
93 93

94
def dewhiten(s):
95
    return whiten(s)        # self inverse
94
def dewhiten(s, o):
95
    return whiten(s, o)        # self inverse
96 96

97 97

98
def make_header(payload_len):
99
    return struct.pack('!HH', payload_len, payload_len)
98
def make_header(payload_len, whitener_offset=0):
99
    # Upper nibble is offset, lower 12 bits is len
100
    val = ((whitener_offset & 0xf) << 12) | (payload_len & 0x0fff)
101
    #print "offset =", whitener_offset, " len =", payload_len, " val=", val
102
    return struct.pack('!HH', val, val)
100 103

101 104
def make_packet(payload, samples_per_symbol, bits_per_symbol,
102
                access_code=default_access_code, pad_for_usrp=True):
105
                access_code=default_access_code, pad_for_usrp=True,
106
                whitener_offset=0):
103 107
    """
104
    Build a packet, given access code and payload.
108
    Build a packet, given access code, payload, and whitener offset
105 109

106 110
    @param payload:               packet payload, len [0, 4096]
107 111
    @param samples_per_symbol:    samples per symbol (needed for padding calculation)
......
109 113
    @param bits_per_symbol:       (needed for padding calculation)
110 114
    @type bits_per_symbol:        int
111 115
    @param access_code:           string of ascii 0's and 1's
116
    @param whitener_offset        offset into whitener string to use [0-16)
112 117
    
113 118
    Packet will have access code at the beginning, followed by length, payload
114 119
    and finally CRC-32.
......
116 121
    if not is_1_0_string(access_code):
117 122
        raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,)
118 123

124
    if not whitener_offset >=0 and whitener_offset < 16:
125
        raise ValueError, "whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,)
126

119 127
    (packed_access_code, padded) = conv_1_0_string_to_packed_binary_string(access_code)
120 128
    (packed_preamble, ignore) = conv_1_0_string_to_packed_binary_string(preamble)
121 129
    
......
127 135
    if L > MAXLEN:
128 136
        raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,)
129 137

130
    pkt = ''.join((packed_preamble, packed_access_code, make_header(L), whiten(payload_with_crc), '\x55'))
138
    pkt = ''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset),
139
                   whiten(payload_with_crc, whitener_offset), '\x55'))
131 140
    if pad_for_usrp:
132 141
        pkt = pkt + (_npadding_bytes(len(pkt), samples_per_symbol, bits_per_symbol) * '\x55')
133 142

......
156 165
    return byte_modulus - r
157 166
    
158 167

159
def unmake_packet(whitened_payload_with_crc):
168
def unmake_packet(whitened_payload_with_crc, whitener_offset=0):
160 169
    """
161 170
    Return (ok, payload)
162 171

163 172
    @param whitened_payload_with_crc: string
164 173
    """
165
    payload_with_crc = dewhiten(whitened_payload_with_crc)
174
    payload_with_crc = dewhiten(whitened_payload_with_crc, whitener_offset)
166 175
    ok, payload = gru.check_crc32(payload_with_crc)
167 176

168 177
    if 0:
b/gnuradio-examples/python/digital/Makefile.am
28 28
	pick_bitrate.py		\
29 29
	receive_path.py		\
30 30
	rx_voice.py		\
31
	run_length.py		\
31 32
	transmit_path.py	\
32 33
	tunnel.py		\
33 34
	tx_voice.py		
b/gnuradio-examples/python/digital/README
75 75

76 76
This now uses a carrier sense MAC, so you should be able to ssh
77 77
between the machines, web browse, etc.
78

79
* run_length.py: This program takes a single argument '-f FILE' and
80
outputs the number of runs of similar bits within the file. It is
81
useful as a diagnostic tool when experimenting with line coding or
82
whitening algorithms.
83

84

b/gnuradio-examples/python/digital/benchmark_tx.py
71 71
                      help="set megabytes to transmit [default=%default]")
72 72
    parser.add_option("","--discontinuous", action="store_true", default=False,
73 73
                      help="enable discontinous transmission (bursts of 5 packets)")
74
    parser.add_option("","--from-file", default=None,
75
                      help="use file for packet contents")
74 76

75 77
    transmit_path.add_options(parser, expert_grp)
76 78

......
89 91
        parser.print_help(sys.stderr)
90 92
        sys.exit(1)
91 93

94
    if options.from_file is not None:
95
        source_file = open(options.from_file, 'r')
96

92 97
    # build the graph
93 98
    fg = my_graph(mods[options.modulation], options)
94 99

......
98 103

99 104
    fg.start()                       # start flow graph
100 105

101

102 106
    # generate and send packets
103 107
    nbytes = int(1e6 * options.megabytes)
104 108
    n = 0
......
106 110
    pkt_size = int(options.size)
107 111

108 112
    while n < nbytes:
109
        send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
110
        n += pkt_size
113
        if options.from_file is None:
114
            data = (pkt_size - 2) * chr(pktno & 0xff) 
115
        else:
116
            data = source_file.read(pkt_size - 2)
117
            if data == '':
118
                break;
119

120
        payload = struct.pack('!H', pktno) + data
121
        send_pkt(payload)
122
        n += len(payload)
111 123
        sys.stderr.write('.')
112 124
        if options.discontinuous and pktno % 5 == 4:
113 125
            time.sleep(1)
b/gnuradio-examples/python/digital/run_length.py
1
#!/usr/bin/env python
2
#
3
# Copyright 2007 Free Software Foundation, Inc.
4
# 
5
# This file is part of GNU Radio
6
# 
7
# GNU Radio is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2, or (at your option)
10
# any later version.
11
# 
12
# GNU Radio is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
# 
17
# You should have received a copy of the GNU General Public License
18
# along with GNU Radio; see the file COPYING.  If not, write to
19
# the Free Software Foundation, Inc., 51 Franklin Street,
20
# Boston, MA 02110-1301, USA.
21
# 
22

23
from optparse import OptionParser
24
import sys
25

26
def main():
27
    parser = OptionParser()
28
    parser.add_option("-f", "--file", default=None,
29
                      help="Choose file to read data from.")
30
    (options, args) = parser.parse_args()
31

32
    if options.file == None:
33
        print "Must specify file to read from using '-f'."
34
        sys.exit(1)
35
    print "Using", options.file, "for data."
36

37
    f = open(options.file, 'r')
38
    runs = []
39
    count = 0
40
    current = 0
41
    bytes = 0
42
    bits = 0
43
    
44
    for ch in f.read():
45
        x = ord(ch)
46
        bytes = bytes + 1
47
        for i in range(7,-1,-1):
48
            bits = bits + 1
49
            t = (x >> i) & 0x1
50
            if t == current:
51
                count = count + 1
52
            else:
53
                if count > 0:
54
                    if len(runs) < count:
55
                        for j in range(count - len(runs)):
56
                            runs.append(0);
57
                    runs[count-1] = runs[count-1] + 1
58

59
                current = 1-current;
60
                count = 1
61

62
    # Deal with last run at EOF
63
    if len(runs) < count and count > 0:
64
        for j in range(count - len(runs)):
65
            runs.append(0);
66
    runs[count-1] = runs[count-1] + 1
67

68
    chk = 0
69
    print "Bytes read: ", bytes
70
    print "Bits read:  ", bits
71
    print
72
    for i in range(len(runs)):
73
        chk = chk + runs[i]*(i+1)
74
        print "Runs of length", i+1, ":", runs[i]
75
    print
76
    print "Sum of runs:", chk, "bits"
77
    print
78
    print "Maximum run length is", len(runs), "bits"
79

80
if __name__ == "__main__":
81
    main()
82

83
    
b/gnuradio-examples/python/digital/transmit_path.py
50 50
        self._samples_per_symbol = options.samples_per_symbol  # desired samples/baud
51 51
        self._fusb_block_size    = options.fusb_block_size # usb info for USRP
52 52
        self._fusb_nblocks       = options.fusb_nblocks    # usb info for USRP
53

53
        self._use_whitener_offset = options.use_whitener_offset # increment start of whitener XOR data
54
        
54 55
        self._modulator_class = modulator_class         # the modulator_class we are using
55 56
    
56 57
        if self._tx_freq is None:
......
80 81
                          self._modulator_class(fg, **mod_kwargs),
81 82
                          access_code=None,
82 83
                          msgq_limit=4,
83
                          pad_for_usrp=True)
84
                          pad_for_usrp=True,
85
                          use_whitener_offset=options.use_whitener_offset)
84 86

85 87

86 88
        # Set the USRP for maximum transmit gain
......
200 202
                          help="set fpga interpolation rate to INTERP [default=%default]")
201 203
        expert.add_option("", "--log", action="store_true", default=False,
202 204
                          help="Log all parts of flow graph to file (CAUTION: lots of data)")
205
        expert.add_option("","--use-whitener-offset", action="store_true", default=False,
206
                          help="make sequential packets use different whitening")
203 207

204 208
    # Make a static method to call before instantiation
205 209
    add_options = staticmethod(add_options)

Also available in: Unified diff