discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] problem with carrier sense in USRP


From: George Nychis
Subject: Re: [Discuss-gnuradio] problem with carrier sense in USRP
Date: Thu, 13 Nov 2008 20:40:25 -0500
User-agent: Thunderbird 2.0.0.17 (X11/20080925)

Collisions are still very likely in a software-defined radio
architecture if you implement the carrier sense mechanism on the host
(your machine running GNU Radio).  If you think about it, carrier sense
needs to check if the medium is idle, if it is, it then sends.
If you think about the USRP and GNU Radio, the information it uses to
check if the medium is idle is as old as it takes to get from the RF
frontend on the USRP to GNU Radio.  That time to get all the way up to
your processing blocks is likely over 1 or 2ms.  Therefore, when it says
"oh, the channel is idle!"  What's is really saying is: "oh, the channel
was idle 1 or 2ms ago."  That essentially breaks carrier sense.

To make matters even worse, when it thinks its captured the channel by
choosing to transmit, the transmission takes another 1ms to actually get
from the carrier sense decision mechanism to the USRP.  So, your carrier
sense is roughly 2ms off, and anything can happen during that period.
This is referred to as a "carrier sense blind-spot."  The larger the
blind-spot, the more poor carrier sense is going to perform.

We have done work here on getting around these high latency issues by
implementing a split-functionality architecture to core MAC functions on
GNU Radio and the USRP.  The idea is: implement part of the function on
the USRP, but leave the control completely at the host.  So for example,
we modified GNU Radio and the USRP where GNU Radio sets the carrier
sense threshold on the USRP, and the USRP performs the carrier sense.
We've measured the blind spot in GNU Radio to be ~2ms, and with our
split-functionality it is ~1.5us.  Major difference.

Our code release is pending on functionality in GNU Radio, and includes many other optimizations for MAC functionality in software-defined radios.

- George


Shirve wrote:
Hi,
I am testing the carrier sense mechanism on USRP based on code from
benchmark_tx.py and tunnel.py. My scenario is to receive packets from two
distinctive nodes simultaneously at the third node. I am prefixing the
payload with sender node name to identify the sender.

When I am trying to send the packets from two nodes simultaneously, the
packets are still colliding, though I have incorporated carrier sense
mechanism in to my code. Please help me in this respect and if possible
suggest me a solution.

I think, packets are being sent by the lower level C++ processing blocks and
send_pkt() just enqueues the packets. So rather than holding sending of
packet, this code is just holding the packet from getting enqueued in
message queue. Which is not really the holding of packet till carrier is
free. Once packets are in message queue, they are transmitted irrespective
of carrier availability. So there is still possibility of packet collision.
Am I correct in my understanding of this real-time scenario?

Attached following is the code of sender application. Receiving application
is more or less similar to benchmark_rx.py with ability to identify the
packets.

Tx_carrier_sense.py

class my_top_block(gr.top_block):
    def __init__(self, modulator, demodulator, rx_callback, options):
        gr.top_block.__init__(self)
        self.txpath = transmit_path(modulator, options)
        self.rxpath = receive_path(demodulator, rx_callback, options)
        self.connect(self.txpath)
        self.connect(self.rxpath)

#
/////////////////////////////////////////////////////////////////////////////
#                                   main
#
/////////////////////////////////////////////////////////////////////////////

def main():

    def send_pkt(payload='', eof=False):
        return tb.txpath.send_pkt(payload, eof)
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass
    def rx_callback(ok, payload):
        print "ok = %r" % (ok)

    def carrier_sensed():
        """  Return True if the receive path thinks there's carrier """
        return tb.rxpath.carrier_sensed()

    demods = modulation_utils.type_1_demods()
    mods = modulation_utils.type_1_mods()

    parser = OptionParser(option_class=eng_option,
conflict_handler="resolve")
    expert_grp = parser.add_option_group("Expert")


    parser.add_option("-m", "--modulation", type="choice",
choices=mods.keys(),
                      default='gmsk',
                      help="Select modulation from: %s [default=%%default]"
                            % (', '.join(mods.keys()),))

    parser.add_option("-s", "--size", type="eng_float", default=1500,
                      help="set packet size [default=%default]")
    parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
                      help="set megabytes to transmit [default=%default]")
    parser.add_option("","--discontinuous", action="store_true",
default=False,
                      help="enable discontinous transmission (bursts of 5
packets)")
    parser.add_option("","--from-file", default=None,
                      help="use file for packet contents")

    receive_path.add_options(parser, expert_grp)
    transmit_path.add_options(parser, expert_grp)

    for mod in mods.values():
        mod.add_options(expert_grp)

    fusb_options.add_options(expert_grp)
    (options, args) = parser.parse_args ()

    if len(args) != 0:
        parser.print_help()
        sys.exit(1)

    if options.tx_freq is None:
        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
        parser.print_help(sys.stderr)
        sys.exit(1)

    if options.from_file is not None:
        source_file = open(options.from_file, 'r')
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass
    # build the graph
    tb = my_top_block(mods[options.modulation], demods[options.modulation],
rx_callback, options)

    r = gr.enable_realtime_scheduling()
    if r != gr.RT_OK:
        print "Warning: failed to enable realtime scheduling"

    tb.start()                       # start flow graph
# generate and send packets
    nbytes = int(1e6 * options.megabytes)
    n = 0
    pktno = 0
    pkt_size = int(options.size)

    min_delay = 0.0001
    while n < nbytes:
        if options.from_file is None:
data = "C-node" + (pkt_size - 8) * chr(pktno & 0xff) else:
            data = source_file.read(pkt_size - 2)
            if data == '':
                break;

        payload = struct.pack('!H', pktno & 0xffff) + data
        delay = min_delay
        while carrier_sensed():
print "sensed" time.sleep(delay)
            if delay < 0.050:
                delay = delay * 2       # exponential back-off

        send_pkt(payload)
        n += len(payload)
        sys.stderr.write('.')
        if options.discontinuous and pktno % 5 == 4:
            time.sleep(0.3) # default = 1
        pktno += 1

    delay = min_delay
    while carrier_sensed():
        time.sleep(delay)
        if delay < 0.050:
            delay = delay * 2       # exponential back-off
send_pkt(eof=True)

    tb.wait()                       # wait for it to finish

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass





reply via email to

[Prev in Thread] Current Thread [Next in Thread]