Bandwidth switching per symbol

Hi,

I’m currently using the UCLA ZigBee Phy implementation by Thomas
Schmid and I need to
change the Bandwidth of the used wireless channel on a per symbol basis.

I managed to change it on a per packet basis, which can be done on the
python level
(tunnel.py, usrp_transmit_path.py etc.). Well now, I need to do the
same thing, but on a
per symbol basis, which (up to my knowledge) is not possible from the
python level…

Does anyone have an idea how I could do that? (Changing the Bitrate of
the USRP after
each symbol (e.g. after sending 32 modulated bits (actually chips)))

I would be very happy for any help or suggestions!
Thanks a lot!

best regards,
Bjorn

Hi,

i think this would be hard on the python level, you would need to notify
the python code after each symbol to make adjustments, which will lead
to latency between symbols …

(As I understand you want to keep the chipping sequences, but change the
sampling rate used for each symbol. You can have the same effect by
changing the interpolation between samples, keeping the rate constant,
and oversampling small bandwidths. )
For this, I would suggest that you add a “per packet schedule” that
specifies the bandwidth of each symbol, and hack the C code to follow
the schedule, changing the interpolation between chips for each symbol.
Something like send_802_15_4_pkt (packet, “1,2,8,2,4,1”), meaning
1MChips/s for the first symbol, 2MChips/s (the default) for the second,
then 8MChips/s, etc. The benefit is that you can go on working on the
packet level in python.
On the C side, you would need to run the flow graph at 16MSamples (to
get 2 samples per chip @ 8MChips/s, basically fast enough to support the
largest bandwidth you want), and decide for each symbol the necessary
interpolation to generate the specified bandwidth (e.g., 16 samples/chip
@1MChips/s).

Regards,
Matthias

Am 27.07.2011 um 13:31 schrieb [email protected]:

Hi,

Thanks a lot for your reply!

This is exactly what I was looking for!
Would you by any chance have an idea in what C level files I could
manipulate the interpolation?

best regards and thank you,
Bjorn

Zitat von “Matthias W.” [email protected]:

Hi,

Do you by any chance know where the corresponding part to:

*out++ = gr_complex(0.0, 0.0);
*out++ = gr_complex(iphase * 0.70710678, qphase * 0.70710678);
*out++ = gr_complex(iphase, qphase);
*out++ = gr_complex(iphase * 0.70710678, qphase * 0.70710678);

is at the receiver?

Could it be that this is in the file: gr_quadrature_demod_cf.cc

for (int i = 0; i < noutput_items; i++){
gr_complex product = in[i] * conj (in[i-1]);
// out[i] = d_gain * arg (product);
out[i] = d_gain * gr_fast_atan2f(imag(product), real(product));
}

that i need to change this part?

best regards, and thanks for your reply

Bjorn

Zitat von “Matthias W.” [email protected]:

Hi,

I think you need to change the the O-QPSK modulator, it’s in
src/lib/ucla_qpsk_modulator_cc.

Currently, for each chip, it expects 2MChips/s and produces 4 complex
samples that specify the shape of the pulse (half a sine wave up for
chip “1” and down for chip “0” or -1):
*out++ = gr_complex(0.0, 0.0);
*out++ = gr_complex(iphase * 0.70710678, qphase * 0.70710678);
*out++ = gr_complex(iphase, qphase);
*out++ = gr_complex(iphase * 0.70710678, qphase * 0.70710678);

If you add more samples per pulse by interpolating in-between (say 8),
you halve the bandwidth while using the same chipping sequence, using
only 2 samples doubles it (when you use a fixed sampling rate).

So if you want to increase the bandwidth, you should first adjust the
default sampling rate/decimation of the ZigBee code as defined in the
python script when initiating the USRP source, from 4MSamples (decim 16)
to a higher value, and adjust the modulation block accordingly (e.g.,
decim 8 -> use 8 samples/chip), so that you still have several samples
per chip even on larger bandwidths (to generate smooth pulses).

The changes are then straight-forward, you just specify different
cases/if clauses and produce a different number of samples for each
symbol (i.e., for a sequence of 32 chips), depending on the bandwidth
you want.

The larger problem may be how to get the “schedule” information from
python to the C code so that it’s synchronized with the sampling stream,
I don’t have much experience on how you can achieve this in GNU Radio. I
think there is a way to attach meta-data to a stream of samples …
Another approach is in-band signaling (interleaving special tags into
the stream of samples that change settings in the blocks and are
filtered out in the end), but I think it’s more of a hack than sound
design.

Matthias

Am 27.07.2011 um 15:22 schrieb [email protected]:

Am 28.07.2011 um 15:56 schrieb [email protected]:

Could it be that this is in the file: gr_quadrature_demod_cf.cc

Bjorn

Hi,

reception is a bit trickier …
The receiver flow graph is constructed in src/python/ieee802_15_4_pkt.py
in class ieee802_15_4_demod_pkts. It is basically [ ieee802_15_4_demod
-> packet_sink/message queue ], first doing an FM demod, filtering, and
clock recovery, then the packet sink is searching for chips and keep
track of the receiver state (search preamble, SFD, frame content, …).

I think you need to change two parts:

  1. src/python/ieee_802_15_4.py, at the class ieee802_15_4_demod, make it
    work at the highest bandwidth you need. quadrature_demod_cf should work
    fine (the chips are decided by a slicer, so sample > 0 -> “1” and sample
    < 0 -> “0”, a larger bandwidth only leads to larger samples after FM
    demod). There is the variable sps (samples per symbol), try to increase
    it for more samples. You must also make sure that the filter and clock
    recovery do the right thing, so tweak the parameters accordingly (no
    idea how to get the clock recovery working across several rates). Since
    at this point you don’t know anything about symbols and their rates,
    your hope is to modify the blocks available to support all rates
    simultaneously.

  2. The packet sink (the code is in
    src/lib/ucla_ieee802_15_4_packet_sink.cc) expects a fixed rate, so you
    should increase the used sampling rate and decimate the low bandwidth
    symbols correctly when they arrive (or maybe this is already solved by
    clock recovery somehow).

The transmitter must send the preamble with a known rate so that you
know what to look for (to be able to find out when the first real symbol
starts), and then use if clauses again to decimate. For this to work,
the receiver must know beforehand which rate the symbols in the preamble
are in and what the schedule for the packet is, if you want to find that
out on the fly, you will likely have to re-implement larger parts of the
receiver.

Regards,
Matthias

Am 29.07.2011 um 13:44 schrieb [email protected]:

*out++ = gr_complex(iphase, qphase);
Now it would be great if I could just tweak the parameters in
“ieee802_15_4_demod”, but how?

clock_recovery and the iir filter are gnuradio specific functions, hence
tweaking the parameters should in general work in a constant BW case, right?

Do you have any suggestions on those parameters?

many thanks and have a good weekend soon,
Bjorn

Hi,

to clarify, do you get a good half packet each time a packet arrives, or
are 50% of the packets good and 50% broken (or undetected)?
I understand that you have something like (g means good symbol, b means
bad):
gggggggggggggbbbbbbbbbbbb
for all packets you see, which would be a rather strange behavior. It
would suggest that everything is working fine and robust for the first
half, and somehow breaks down in-between.
My remote diagnose in this case is that the state machine in the packet
sink detects the preamble and SFD (and maybe the header as well) for
each packet, but has some hard-coded parts that expects the default
bandwidth, producing arbitrary results for the rest of the packet. You
should check how far the state machine works correctly, and debug the
problem case. You can active the debug symbols in the UCLA code (VERBOSE
and VERBOSE2) to see what is happening in the state machine of the
receiver.

If it’s 50/50% good/bad packets, then I would suspect the timing
recovery, but the parameters are also rather magical for me. But I think
its the standard(?) Mueller&Mller clock recovery algorithm, so there
should be some info in textbooks how it works and what parameters are
suitable. I found this:
http://www.mail-archive.com/[email protected]/msg12723.html

Regards,
Matthias

Hi,

Well its the first case (strange behavior)
(g means good symbol, b means bad): gggggggggggggbbbbbbbbbbbb

more precisely, Preamble, SFD, packet length (PHR) is all received
correctly. Additionally, also a part of the payload is received
correctly. Here an example:

I send the following packet:
[‘0x0’, ‘0x0’, ‘0x0’, ‘0x0’, ‘0xa7’, ‘0x19’, ‘0x1’, ‘0x0’, ‘0xff’,
‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’,
‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’,
‘0x68’, ‘0x44’, ‘0x0’]

and receive the following:
[‘0x0’, ‘0x0’, ‘0x0’, ‘0x0’, ‘0xa7’, ‘0x19’, ‘0x1’, ‘0x0’, ‘0xff’,
‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xca’, ‘0x8f’,
‘0x45’, ‘0xa5’, ‘0x79’, ‘0xab’, ‘0x35’, ‘0x9a’, ‘0x8c’, ‘0x32’,
‘0xf9’, ‘0x8c’, ‘0xa0’, ‘0xba’, ‘0x2’]

If this would be during the packet_sink, then the error would occur
somewhere in the middle of decode_chips()…

best regards, and thanks again
Bjorn

Quoting “Matthias W.” [email protected]:

Hi,

As it turns out, the verbose output isn’t that helpful either. It just
reveals that at some point, the chip-error rate increases drastically.
See the verbose output of receiving one packet below:

Found 0 in chip sequence
Found 1 0 in chip sequence
Found 2 0 in chip sequence
Found 3 0 in chip sequence
Found 4 0 in chip sequence
Found 5 0 in chip sequence
Found 6 0 in chip sequence
Found 7 0 in chip sequence
Found first SFD
Found sync, 0x7a
@ enter_have_sync
Header Search bitcnt=0, header=0x00000000
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
@ enter_have_header (payload_len = 25)
Packet Build count=101, noutput_items=256, packet_len=25
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 0, payloadcnt: 0, payload 0x1, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 1, payloadcnt: 1, payload 0x0, d_packet_byte_index: 2
Packet Build count=0, noutput_items=132, packet_len=25
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 2, payloadcnt: 2, payload 0xff, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 3, payloadcnt: 3, payload 0xb, d_packet_byte_index: 2
Packet Build count=0, noutput_items=512, packet_len=25
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 4, payloadcnt: 4, payload 0xb, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 5, payloadcnt: 5, payload 0xb, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 6, payloadcnt: 6, payload 0xb, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 7, payloadcnt: 7, payload 0xb, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 8, payloadcnt: 8, payload 0xb, d_packet_byte_index: 2
Found sequence with 0 errors at 0x0
Found sequence with 0 errors at 0x0
packetcnt: 9, payloadcnt: 9, payload 0xb, d_packet_byte_index: 2
Found sequence with 11 errors at 0x10c99928
Found sequence with 13 errors at 0x330985b8
packetcnt: 10, payloadcnt: 10, payload 0x9e, d_packet_byte_index: 2
Found sequence with 11 errors at 0x1350324a
Found sequence with 11 errors at 0x24a50958
packetcnt: 11, payloadcnt: 11, payload 0xfc, d_packet_byte_index: 2
Packet Build count=0, noutput_items=508, packet_len=25
Found sequence with 11 errors at 0x24688e44
Found sequence with 10 errors at 0x4938588
packetcnt: 12, payloadcnt: 12, payload 0x97, d_packet_byte_index: 2
Found sequence with 12 errors at 0x3046c256
Found sequence with 10 errors at 0x6ac08430
packetcnt: 13, payloadcnt: 13, payload 0x93, d_packet_byte_index: 2
Found sequence with 10 errors at 0x585a8018
Found sequence with 8 errors at 0x3550840
packetcnt: 14, payloadcnt: 14, payload 0x19, d_packet_byte_index: 2
Found sequence with 11 errors at 0x340181ba
Found sequence with 10 errors at 0x540910c6
packetcnt: 15, payloadcnt: 15, payload 0xdf, d_packet_byte_index: 2
Found sequence with 6 errors at 0x5210082
Found sequence with 9 errors at 0x10a224c2
packetcnt: 16, payloadcnt: 16, payload 0xb9, d_packet_byte_index: 2
Found sequence with 10 errors at 0x4c2852a0
Found sequence with 12 errors at 0x42d28a86
packetcnt: 17, payloadcnt: 17, payload 0xac, d_packet_byte_index: 2
Found sequence with 10 errors at 0x26465804
Found sequence with 10 errors at 0x53e02280
packetcnt: 18, payloadcnt: 18, payload 0xfa, d_packet_byte_index: 2
Found sequence with 11 errors at 0x10964dc
Found sequence with 9 errors at 0xa202466
packetcnt: 19, payloadcnt: 19, payload 0xbd, d_packet_byte_index: 2
Packet Build count=0, noutput_items=512, packet_len=25
Found sequence with 11 errors at 0x4a502e6
Found sequence with 10 errors at 0x30a641c
packetcnt: 20, payloadcnt: 20, payload 0x70, d_packet_byte_index: 2
Found sequence with 11 errors at 0x3c47308
Found sequence with 10 errors at 0x2612aa20
packetcnt: 21, payloadcnt: 21, payload 0xe1, d_packet_byte_index: 2
Found sequence with 10 errors at 0x18e32210
Found sequence with 12 errors at 0x4836a622
packetcnt: 22, payloadcnt: 22, payload 0x53, d_packet_byte_index: 2
Found sequence with 11 errors at 0x68c13908
Found sequence with 12 errors at 0x2d14189a
packetcnt: 23, payloadcnt: 23, payload 0x6f, d_packet_byte_index: 2
Found sequence with 12 errors at 0x4a170938
Found sequence with 11 errors at 0x4c059924
packetcnt: 24, payloadcnt: 24, payload 0xc3, d_packet_byte_index: 2
Adding message of size 25 to queue
@ enter_search
received packet
payload:
[‘0x1’, ‘0x0’, ‘0xff’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’, ‘0xb’,
‘0xb’, ‘0x9e’, ‘0xfc’, ‘0x97’, ‘0x93’, ‘0x19’, ‘0xdf’, ‘0xb9’, ‘0xac’,
‘0xfa’, ‘0xbd’, ‘0x70’, ‘0xe1’, ‘0x53’, ‘0x6f’, ‘0xc3’]
checksum: 14309, received: 50031
Rx: ok = False len(payload) = 20
802_15_4_pkt: waiting for packet

Quoting “Matthias W.” [email protected]:

Hi again,

Thanks a lot for your mail from yesterday!

In order to figure out what changes are needed at the receiver, I do
not change the bandwidth per symbol, but constantly, by using the
following lines within ucla_qpsk_modulator_cc.cc.

*out++ = gr_complex(0.0, 0.0);
*out++ = gr_complex(iphase * 0.38268343, qphase * 0.38268343);
*out++ = gr_complex(iphase * 0.70710678, qphase * 0.70710678);
*out++ = gr_complex(iphase * 0.92387953, qphase * 0.92387953);
*out++ = gr_complex(iphase, qphase);
*out++ = gr_complex(iphase * 0.92387953, qphase * 0.92387953);
*out++ = gr_complex(iphase * 0.70710678, qphase * 0.70710678);
*out++ = gr_complex(iphase * 0.38268343, qphase * 0.38268343);

Now in the file: ieee802_15_4.py @ ieee802_15_4_demod
I have changed the variable sps from 2 to 4, as previously suggested.
The result is, that the receiver receives half the packet correctly,
and the whole second half appears to be random.

I don’t think that we need to change the file
“ucla_ieee802_15_4_packet_sink.cc” in this case.

Now it would be great if I could just tweak the parameters in
“ieee802_15_4_demod”, but how?

clock_recovery and the iir filter are gnuradio specific functions,
hence tweaking the parameters should in general work in a constant BW
case, right?

Do you have any suggestions on those parameters?

many thanks and have a good weekend soon,
Bjorn

Quoting “Matthias W.” [email protected]:

Hi

I figured it out… the problem was just the sender itself.
I forgot to change the parameter: static const int SAMPLES_PER_SYMBOL =
4;
to: static const int SAMPLES_PER_SYMBOL = 8;
in “ucla_qpsk_modulator_cc.cc”

At the receiver side, I actually only had to change the variable
“sps”. I guess the filter and clock recovery still work, as the
parameter of those are influenced by the variable sps.

Well thank you for all your help! I hope I can get even some day…

best regards,
Bjorn

Quoting “Matthias W.” [email protected]:

Hi,

this seems really strange, some ideas for debugging:

  1. the demod process works fine at first but adds or drops a few samples
    such that some chips a shifted a bit, and as the chip seqs of 802.15.4
    are just shifted/inverted version of each other so that you see many
    different symbols in the end.
    You can print the input to the packet_sink (after slicing) and see if
    they resemble shifted version of the sequences you expect. The debug
    messages also mention how many chip errors were found, if the receiver
    had too many chip errors and restarted, etc.

  2. Is the problem always after 32 symbols? (32 symbols * 32 chips, …)
    This would suggest a “digital” problem. Buffers too small or something?

  3. The error may be at the sender, shifting the symbols a bit in the
    middle of the packet so that the receiver has problems with sync (or
    just sends bogus after 32 symbols). You can monitor (scope sink) with a
    second USRP if the signal looks alright.

Regards,
Matthias

Am 29.07.2011 um 14:36 schrieb [email protected]:

Hi,

I’m using the UCLA ZIGBEE PHY implementation by Thomas S.:

Does anyone have an idea, how I could build a connection/communication
between the files/functions in the files:

  • ucla_clock_recovery_ff_mm.cc
  • ucla_ieee802_15_4_packet_sink.cc

such that a variable within clock_recovery is changed whenever a
symbol has been successfully decoded in the packet_sink?

Well I only need to know how I could build up this connection between
the two files mentioned above. Does anyone have an idea?

I appreciate any comments on this…

best regards,
Bjorn

Hi,

I’m currently using the UCLA ZigBee PHY implementation by Thomas
Schmid and have got the following question:

In the file “clock_recovery_mm_ff.cc” is a parameter “omega”, which I
would like to change from within “ucla_ieee802_15_4_packet_sink.cc”.

Now there is the public function:
void set_omega(float omega)

but I wasn’t able to access it from within the packet_sink.

Does anyone have a clue/idea how I could achieve this?

best regards and thank you for any help!
Bjorn

On Thu, Aug 4, 2011 at 7:24 AM, [email protected] wrote:

but I wasn’t able to access it from within the packet_sink.

Does anyone have a clue/idea how I could achieve this?

best regards and thank you for any help!
Bjorn

I’m not familiar with the Zigbee code, but normally, we create set/get
functions in the .cc and .h files, then they have to be exported to
Python though the Swig .i interface file. If you aren’t seeing this
function in the Python module, look at the block’s .i file to see if
the function exists there. If it doesn’t, just copy and paste it from
the .h file and rebuild and install.

Tom